[1.2]由UML模型通过XMI生成XML,通过XSLT展示到表现层
2005-03-28 14:30
351 查看
本专栏当前的话题是建模、UML 和 XML。具体而言,即研究 UML 建模在 XML 开发中的应用,特别是如何用 XSLT 样式表实现自动派生。
随着 XML 成为开发项目的一种常见特性,很多开发人员对把 XML 和开发过程中的其他部分结合起来越来越感兴趣。尽管许多组织仍然依靠专门的工具进行 XML 开发,但大的趋势是在 XML 的开发中采用其他开发需求已经使用的方法论,或者至少是一组通用的工具,比如 Java 技术、数据库和 Web。
自动派生
上一期已经指出,模型是帮助计算和预测的系统简化描述。在本文的环境中,所谓系统指的都是 XML 词汇表。
图 1 表示的是模型连续体(continuum)的建模过程。第一个模型是画在白板(或者一沓纸)上的,一般不那么正规。这个阶段的目标是让所有的参与者(用户、开发人员和设计人员)有机会自由地表达自己的观点。
图 1. 模型连续体
<?xml version="1.0"?>
<XMI xmi.version="1.2" xmlns:UML="org.omg/UML/1.4">
<XMI.header>
<XMI.documentation>
<XMI.exporter>ananas.org stylesheet</XMI.exporter>
</XMI.documentation>
<XMI.metamodel xmi.name="UML" xmi.version="1.4"/>
</XMI.header>
<XMI.content>
<UML:Model xmi.id="M.1" name="address" visibility="public"
isSpecification="false" isRoot="false"
isLeaf="false" isAbstract="false">
<UML:Namespace.ownedElement>
<UML:Class xmi.id="C.1" name="address" visibility="public"
isSpecification="false" namespace="M.1" isRoot="true"
isLeaf="true" isAbstract="false" isActive="false">
<UML:Classifier.feature>
<UML:Attribute xmi.id="A.1" name="name" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.2" name="street" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.3" name="zip" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.4" name="region" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.5" name="city" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.6" name="country" visibility="private"
isSpecification="false" ownerScope="instance"/>
</UML:Classifier.feature>
</UML:Class>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
要注意,清单 1 中的 XML 元素和属性是如何与 图 2 中的类和属性匹配的。您现在又回到了原地:XMI 文档是 UML 元模型的直接表示,因为 UML 元模型是 UML 本身的描述。
表示的问题
UML 元模型的一部分处理概念的可视化表示——把概念画到屏幕的何处。由于两方面的原因我的样式表中没有处理这些信息:
从 UML 模型派生出 XML 模式不需要这些信息。
从 XML 模式派生 UML 模型时生成可视化的输出非常困难。更合理的选择是用建模工具打开模型,花几分钟准备模型在屏幕上的可视化表示。最困难的工作(正确的定义)已经由样式表完成了。
XSLT 样式表
现在您已经掌握了阅读 XMI 文件的要点,很容易就能把 XMI 标签映射成等价的 XML 模式。一种可能的映射是:
清单 2 是实现这种映射的 XSLT 样式表:
清单 2. XML 模式派生
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:UML="org.omg/UML/1.4"
exclude-result-prefixes="UML"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="XMI[@xmi.version='1.2']">
<xsl:apply-templates select="XMI.content/UML:Model"/>
</xsl:template>
<xsl:template match="XMI">
<xsl:message terminate="yes">Unknown XMI version</xsl:message>
</xsl:template>
<xsl:template match="UML:Model">
<xs:schema targetNamespace="http://psol.com/uml/{@name}">
<xsl:apply-templates/>
</xs:schema>
</xsl:template>
<xsl:template match="UML:Namespace.ownedElement/UML:Class">
<xs:element name="{@name}">
<xs:complexType>
<xs:sequence>
<xsl:apply-templates/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsl:template>
<xsl:template match="UML:Attribute">
<xs:element name="{@name}" type="xs:string"/>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
</xsl:stylesheet>
显然,清单 2 中的样式表功能非常有限(只进行了很少的错误检查),因为它仅仅支持 UML 元模型很小的一个子集。它没有考虑包、接口、关联等等。只需要对上面描述的过程稍加扩展,就可以进一步完善这个样式表以支持上述概念:研究 UML 元模型中相应的部分、定义到 XML 模式的映射然后实现它。
反过来一样
如果遵循常规的建模流程,很容易得到 清单 2。您经常会发现已经存在一个 XML 模式,可以作为工作的起点。重新建立 UML 模型太麻烦了,如果由一个样式表实现逆映射会非常方便。清单 3 是一个例子:
清单 3. 逆派生(从 XML 模式到 UML)
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:UML="org.omg/UML/1.4"
exclude-result-prefixes="xs"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="xs:schema">
<XMI xmi.version="1.2">
<XMI.header>
<XMI.documentation>
<XMI.exporter>dW simple stylesheet</XMI.exporter>
</XMI.documentation>
<XMI.metamodel xmi.name="UML" xmi.version="1.4"/>
</XMI.header>
<XMI.content>
<UML:Model xmi.id="{generate-id()}"
name="{substring-after(@targetNamespace,'http://psol.com/uml/')}"
visibility="public" isSpecification="false"
isRoot="false" isLeaf="false" isAbstract="false">
<UML:Namespace.ownedElement>
<xsl:apply-templates/>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
</xsl:template>
<xsl:template match="xs:element">
<UML:Class xmi.id="{generate-id()}" name="{@name}"
visibility="public" isSpecification="false" isRoot="true"
isLeaf="true" isAbstract="false" isActive="false">
<xsl:apply-templates/>
</UML:Class>
</xsl:template>
<xsl:template match="xs:sequence">
<UML:Classifier.feature>
<xsl:apply-templates/>
</UML:Classifier.feature>
</xsl:template>
<xsl:template match="xs:sequence/xs:element">
<UML:Attribute xmi.id="{generate-id(.)}" name="{@name}"
visibility="private" isSpecification="false"
ownerScope="instance"/>
</xsl:template>
</xsl:stylesheet>
更复杂的样式表
如果要说本文中介绍的样式表很简单,就太过谨慎了。这些例子一般不到 50 行,只能处理 UML 元模型的一个子集。实际的样式表能够识别多得多的 UML 概念,通常需要 500 行甚至更多。本期文章的目标是介绍自动化模型派生背后的概念:
这些模型(UML、XML 模式)都用一个数据集表示,这种特殊的数据集称为元模型。
可以建立 UML 元模型和 XML 模式之间的映射。
可以通过 XSLT 样式表实现这种映射。
UML 和 XML 模式仅仅是同一事实的不同表示,区别在于服务于不同的目标。
如果您尝试扩展 清单 2 和 清单 3 中的样式表,可能会遇到两个问题:
UML 模型可能不够具体(因为是一种高级视图),无法派生出有意义的 XML 模式(低级的、详细的模型)。
UML 元模型和 XML 模式之间可能存在多种合理的映射。
随着 XML 成为开发项目的一种常见特性,很多开发人员对把 XML 和开发过程中的其他部分结合起来越来越感兴趣。尽管许多组织仍然依靠专门的工具进行 XML 开发,但大的趋势是在 XML 的开发中采用其他开发需求已经使用的方法论,或者至少是一组通用的工具,比如 Java 技术、数据库和 Web。
自动派生
上一期已经指出,模型是帮助计算和预测的系统简化描述。在本文的环境中,所谓系统指的都是 XML 词汇表。
图 1 表示的是模型连续体(continuum)的建模过程。第一个模型是画在白板(或者一沓纸)上的,一般不那么正规。这个阶段的目标是让所有的参与者(用户、开发人员和设计人员)有机会自由地表达自己的观点。
图 1. 模型连续体
<?xml version="1.0"?>
<XMI xmi.version="1.2" xmlns:UML="org.omg/UML/1.4">
<XMI.header>
<XMI.documentation>
<XMI.exporter>ananas.org stylesheet</XMI.exporter>
</XMI.documentation>
<XMI.metamodel xmi.name="UML" xmi.version="1.4"/>
</XMI.header>
<XMI.content>
<UML:Model xmi.id="M.1" name="address" visibility="public"
isSpecification="false" isRoot="false"
isLeaf="false" isAbstract="false">
<UML:Namespace.ownedElement>
<UML:Class xmi.id="C.1" name="address" visibility="public"
isSpecification="false" namespace="M.1" isRoot="true"
isLeaf="true" isAbstract="false" isActive="false">
<UML:Classifier.feature>
<UML:Attribute xmi.id="A.1" name="name" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.2" name="street" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.3" name="zip" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.4" name="region" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.5" name="city" visibility="private"
isSpecification="false" ownerScope="instance"/>
<UML:Attribute xmi.id="A.6" name="country" visibility="private"
isSpecification="false" ownerScope="instance"/>
</UML:Classifier.feature>
</UML:Class>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
要注意,清单 1 中的 XML 元素和属性是如何与 图 2 中的类和属性匹配的。您现在又回到了原地:XMI 文档是 UML 元模型的直接表示,因为 UML 元模型是 UML 本身的描述。
表示的问题
UML 元模型的一部分处理概念的可视化表示——把概念画到屏幕的何处。由于两方面的原因我的样式表中没有处理这些信息:
从 UML 模型派生出 XML 模式不需要这些信息。
从 XML 模式派生 UML 模型时生成可视化的输出非常困难。更合理的选择是用建模工具打开模型,花几分钟准备模型在屏幕上的可视化表示。最困难的工作(正确的定义)已经由样式表完成了。
XSLT 样式表
现在您已经掌握了阅读 XMI 文件的要点,很容易就能把 XMI 标签映射成等价的 XML 模式。一种可能的映射是:
UML:Model变成
xs:schema;目标名称空间从模型名导出。
UML:Class变成全局 XML 元素声明(
xs:element)。
UML:Attribute变成本地 XML 元素声明(
xs:element)。
清单 2 是实现这种映射的 XSLT 样式表:
清单 2. XML 模式派生
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:UML="org.omg/UML/1.4"
exclude-result-prefixes="UML"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="XMI[@xmi.version='1.2']">
<xsl:apply-templates select="XMI.content/UML:Model"/>
</xsl:template>
<xsl:template match="XMI">
<xsl:message terminate="yes">Unknown XMI version</xsl:message>
</xsl:template>
<xsl:template match="UML:Model">
<xs:schema targetNamespace="http://psol.com/uml/{@name}">
<xsl:apply-templates/>
</xs:schema>
</xsl:template>
<xsl:template match="UML:Namespace.ownedElement/UML:Class">
<xs:element name="{@name}">
<xs:complexType>
<xs:sequence>
<xsl:apply-templates/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsl:template>
<xsl:template match="UML:Attribute">
<xs:element name="{@name}" type="xs:string"/>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
</xsl:stylesheet>
显然,清单 2 中的样式表功能非常有限(只进行了很少的错误检查),因为它仅仅支持 UML 元模型很小的一个子集。它没有考虑包、接口、关联等等。只需要对上面描述的过程稍加扩展,就可以进一步完善这个样式表以支持上述概念:研究 UML 元模型中相应的部分、定义到 XML 模式的映射然后实现它。
反过来一样
如果遵循常规的建模流程,很容易得到 清单 2。您经常会发现已经存在一个 XML 模式,可以作为工作的起点。重新建立 UML 模型太麻烦了,如果由一个样式表实现逆映射会非常方便。清单 3 是一个例子:
清单 3. 逆派生(从 XML 模式到 UML)
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:UML="org.omg/UML/1.4"
exclude-result-prefixes="xs"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="xs:schema">
<XMI xmi.version="1.2">
<XMI.header>
<XMI.documentation>
<XMI.exporter>dW simple stylesheet</XMI.exporter>
</XMI.documentation>
<XMI.metamodel xmi.name="UML" xmi.version="1.4"/>
</XMI.header>
<XMI.content>
<UML:Model xmi.id="{generate-id()}"
name="{substring-after(@targetNamespace,'http://psol.com/uml/')}"
visibility="public" isSpecification="false"
isRoot="false" isLeaf="false" isAbstract="false">
<UML:Namespace.ownedElement>
<xsl:apply-templates/>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
</xsl:template>
<xsl:template match="xs:element">
<UML:Class xmi.id="{generate-id()}" name="{@name}"
visibility="public" isSpecification="false" isRoot="true"
isLeaf="true" isAbstract="false" isActive="false">
<xsl:apply-templates/>
</UML:Class>
</xsl:template>
<xsl:template match="xs:sequence">
<UML:Classifier.feature>
<xsl:apply-templates/>
</UML:Classifier.feature>
</xsl:template>
<xsl:template match="xs:sequence/xs:element">
<UML:Attribute xmi.id="{generate-id(.)}" name="{@name}"
visibility="private" isSpecification="false"
ownerScope="instance"/>
</xsl:template>
</xsl:stylesheet>
更复杂的样式表
如果要说本文中介绍的样式表很简单,就太过谨慎了。这些例子一般不到 50 行,只能处理 UML 元模型的一个子集。实际的样式表能够识别多得多的 UML 概念,通常需要 500 行甚至更多。本期文章的目标是介绍自动化模型派生背后的概念:
这些模型(UML、XML 模式)都用一个数据集表示,这种特殊的数据集称为元模型。
可以建立 UML 元模型和 XML 模式之间的映射。
可以通过 XSLT 样式表实现这种映射。
UML 和 XML 模式仅仅是同一事实的不同表示,区别在于服务于不同的目标。
如果您尝试扩展 清单 2 和 清单 3 中的样式表,可能会遇到两个问题:
UML 模型可能不够具体(因为是一种高级视图),无法派生出有意义的 XML 模式(低级的、详细的模型)。
UML 元模型和 XML 模式之间可能存在多种合理的映射。
相关文章推荐
- [1.3].[由UML模型通过XMI生成XML,通过XSLT展示到表现层]
- 使用 IBM Rational Software Architect 通过编程方式生成 UML 模型
- 使用 XML: UML、XMI 和代码生成,第 2 部分
- 使用 IBM Rational Software Architect 通过编程方式生成 UML 模型
- 使用 XML: UML、XMI 和代码生成,第 3 部分
- 使用 XML: UML、XMI 和代码生成,第 4 部分
- IBM Rational Software Architect 通过编程方式生成UML模型
- IBM Rational Software Architect 通过编程方式生成UML模型
- 使用 XML: UML、XMI 和代码生成,第 1 部分
- 如何通过三维网格自动生成纸制模型
- xslt生成xml出现特殊字符Â处理方法
- PowerDesigner(八)-面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,
- 【重要】XSLT学习(九)通过JavaScript转化xml
- Java通过XML字符串生成XML物理文件
- Android学习笔记_31_通过后台代码生成View对象以及动态加载XML布局文件到LinearLayout
- 通过LINQ to XML生成 XML
- mac版 MyBatis Generator 通过xml生成,有日志但是没有生成文件生成
- android的不通过xml添加组件,用new来生成组件。(加载的小圆圈)
- 通过mybatis工具generatorConfig.xml自动生成实体,DAO,映射文件
- DOM模型的XML文件生成读取