使用 XSLT 转换后保留 XML 文件的层次结构(顺序)
keep the hierarchy (order) of an XML file after transformation with XSLT
我正在尝试将一个 XML 文件转换为另一个文件,但我在保持输入文件的相同层次结构方面遇到了问题。
这是输入:
<XMI xmi.version='1.2' xmlns:UML="org.omg.xmi.namespace.UML">
<XMI.content>
<UML:Model xmi.id='eee_1045467100313_135436_1' name='Data'>
<UML:Namespace.ownedElement>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_23' name='migration_kbir'>
<UML:Namespace.ownedElement>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_22' name='migration_s8ir'>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_22' name='migration_s8ir2'>
<UML:Class xmi.id='_9_0_bc102e5_1427367042666_255023_151' name='Employee'>
<UML:Classifier.feature>
<UML:Attribute xmi.id='_9_0_bc102e5_1427367052819_893122_168' name='cin'>
</UML:Attribute>
</UML:Classifier.feature>
</UML:Class>
<UML:Class xmi.id='_9_0_64701d4_1429716452808_363115_43' name='AssoEmpl'>
</UML:Class>
<UML:Generalization xmi.id='_9_0_64701d4_1429719509242_100032_198' child='_9_0_64701d4_1429719498101_197360_182' parent='_9_0_64701d4_1429716437842_892182_26' />
</UML:Package>
</UML:Package>
</UML:Namespace.ownedElement>
</UML:Package>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
这是我得到的输出:
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML"
xmi.version="2.1" timestamp="">
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_23" name="migration_kbir" />
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir" />
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir2">
<packagedElement xmi:type="uml:Class"
xmi.id="_9_0_bc102e5_1427367042666_255023_151" name="Employee">
<generalization xmi.id="_9_0_bc102e5_1427367042666_255023_151">
<general xmi:type="uml:Class" />
</generalization>
<ownedAttribute xmi.id="_9_0_bc102e5_1427367052819_893122_168"
name="cin" />
</packagedElement>
<packagedElement xmi:type="uml:Class"
xmi.id="_9_0_64701d4_1429716452808_363115_43" name="AssoEmpl">
<generalization xmi.id="_9_0_64701d4_1429716452808_363115_43">
<general xmi:type="uml:Class" />
</generalization>
</packagedElement>
</packagedElement>
</xmi:XMI>
但我期待这样的结果:
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML" xmi.version="2.1" timestamp="">
<packagedElement xmi:type="uml:package" xmi.id="_9_0_bc102e5_1427365805826_580042_23" name="migration_kbir">
<packagedElement xmi:type="uml:package"xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir">
<packagedElement xmi:type="uml:package"xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir2">
<packagedElement xmi:type="uml:Class"xmi.id="_9_0_bc102e5_1427367042666_255023_151" name="Employee">
<generalization xmi.id="_9_0_bc102e5_1427367042666_255023_151">
<general xmi:type="uml:Class" />
</generalization>
<ownedAttribute xmi.id="_9_0_bc102e5_1427367052819_893122_168"name="cin" />
</packagedElement>
<packagedElement xmi:type="uml:Class" xmi.id="_9_0_64701d4_1429716452808_363115_43" name="AssoEmpl">
<generalization xmi.id="_9_0_64701d4_1429716452808_363115_43">
<general xmi:type="uml:Class" />
</generalization>
</packagedElement>
</packagedElement>
</packagedElement>
</packagedElement>
</xmi:XMI>
最后是我的转换文件:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:UML="org.omg.xmi.namespace.UML"
xmlns:xmi="http://www.omg.org/XMI"
>
<xsl:output indent="yes" method="xml" />
<xsl:template match="/">
<xmi:XMI>
<xsl:attribute name="xmi.version">2.1</xsl:attribute>
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp" />
</xsl:attribute>
<xsl:for-each select="//UML:Package">
<packagedElement>
<xsl:attribute name="xmi:type">uml:package</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<xsl:choose>
<xsl:when test="UML:Class">
<xsl:for-each select="UML:Class">
<packagedElement>
<xsl:attribute name="xmi:type">uml:Class</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<generalization>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<general xmi:type="uml:Class" />
</generalization>
<xsl:for-each select="UML:Classifier.feature/UML:Attribute">
<ownedAttribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
</ownedAttribute>
</xsl:for-each>
</packagedElement>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</packagedElement>
</xsl:for-each>
</xmi:XMI>
</xsl:template>
</xsl:stylesheet>
我应该在转换代码中做什么来保持输入文件的层次结构?
当你这样做时:
<xsl:for-each select="//UML:Package">
您正在选择文档中的 所有 UML:Package
元素,任意位置,并将它们视为兄弟姐妹。由于这不是您想要的,因此您需要更改方法并改为递归应用模板。
我已经对您现有的样式表进行了快速调整,看看是否适合您:
<xsl:stylesheet xmlns:UML="org.omg.xmi.namespace.UML" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xmi:XMI xmi.version="2.1">
<xsl:attribute name="xmi.version">2.1</xsl:attribute>
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp"/>
</xsl:attribute>
<xsl:apply-templates/>
</xmi:XMI>
</xsl:template>
<xsl:template match="UML:Package">
<packagedElement>
<xsl:attribute name="xmi:type">uml:package</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="UML:Class">
<xsl:for-each select="UML:Class">
<packagedElement>
<xsl:attribute name="xmi:type">uml:Class</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<generalization>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<general xmi:type="uml:Class"/>
</generalization>
<xsl:for-each select="UML:Classifier.feature/UML:Attribute">
<ownedAttribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
</ownedAttribute>
</xsl:for-each>
</packagedElement>
</xsl:for-each>
</xsl:when>
</xsl:choose>
<xsl:apply-templates/>
</packagedElement>
</xsl:template>
</xsl:stylesheet>
注意:
您应该了解如何将属性直接添加到文字结果元素,以及如何使用属性值模板。这可以大大简化您的样式表。
这个:
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp"/>
</xsl:attribute>
在根节点的上下文中没有任何意义
属性.
如果您想要 推送式 类型的样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:UML="org.omg.xmi.namespace.UML"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xmi="http://www.omg.org/XMI">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" method="xml" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="XMI">
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML"
xmi.version="2.1" timestamp="">
<xsl:apply-templates/>
</xmi:XMI>
</xsl:template>
<xsl:template match="UML:Package">
<packagedElement xmi:type="umi:package">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</packagedElement>
</xsl:template>
<xsl:template match="UML:Class">
<packagedElement xmi:type="uml:Class">
<xsl:copy-of select="@*"/>
<xsl:choose>
<xsl:when test="UML:Classifier.feature">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<generalization xmi.id="{../@xmi.id}">
<general xmi:type="uml:Class" />
</generalization>
</xsl:otherwise>
</xsl:choose>
</packagedElement>
</xsl:template>
<xsl:template match="UML:Classifier.feature">
<generalization xmi.id="{../@xmi.id}">
<general xmi:type="uml:Class" />
</generalization>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="UML:Attribute">
<ownedAttribute>
<xsl:copy-of select="@*"/>
</ownedAttribute>
</xsl:template>
<xsl:template match="XMI.content|UML:Model|UML:Namespace.ownedElement">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="UML:Generalization"/>
</xsl:stylesheet>
我正在尝试将一个 XML 文件转换为另一个文件,但我在保持输入文件的相同层次结构方面遇到了问题。
这是输入:
<XMI xmi.version='1.2' xmlns:UML="org.omg.xmi.namespace.UML">
<XMI.content>
<UML:Model xmi.id='eee_1045467100313_135436_1' name='Data'>
<UML:Namespace.ownedElement>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_23' name='migration_kbir'>
<UML:Namespace.ownedElement>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_22' name='migration_s8ir'>
<UML:Package xmi.id='_9_0_bc102e5_1427365805826_580042_22' name='migration_s8ir2'>
<UML:Class xmi.id='_9_0_bc102e5_1427367042666_255023_151' name='Employee'>
<UML:Classifier.feature>
<UML:Attribute xmi.id='_9_0_bc102e5_1427367052819_893122_168' name='cin'>
</UML:Attribute>
</UML:Classifier.feature>
</UML:Class>
<UML:Class xmi.id='_9_0_64701d4_1429716452808_363115_43' name='AssoEmpl'>
</UML:Class>
<UML:Generalization xmi.id='_9_0_64701d4_1429719509242_100032_198' child='_9_0_64701d4_1429719498101_197360_182' parent='_9_0_64701d4_1429716437842_892182_26' />
</UML:Package>
</UML:Package>
</UML:Namespace.ownedElement>
</UML:Package>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
</XMI>
这是我得到的输出:
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML"
xmi.version="2.1" timestamp="">
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_23" name="migration_kbir" />
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir" />
<packagedElement xmi:type="uml:package"
xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir2">
<packagedElement xmi:type="uml:Class"
xmi.id="_9_0_bc102e5_1427367042666_255023_151" name="Employee">
<generalization xmi.id="_9_0_bc102e5_1427367042666_255023_151">
<general xmi:type="uml:Class" />
</generalization>
<ownedAttribute xmi.id="_9_0_bc102e5_1427367052819_893122_168"
name="cin" />
</packagedElement>
<packagedElement xmi:type="uml:Class"
xmi.id="_9_0_64701d4_1429716452808_363115_43" name="AssoEmpl">
<generalization xmi.id="_9_0_64701d4_1429716452808_363115_43">
<general xmi:type="uml:Class" />
</generalization>
</packagedElement>
</packagedElement>
</xmi:XMI>
但我期待这样的结果:
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML" xmi.version="2.1" timestamp="">
<packagedElement xmi:type="uml:package" xmi.id="_9_0_bc102e5_1427365805826_580042_23" name="migration_kbir">
<packagedElement xmi:type="uml:package"xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir">
<packagedElement xmi:type="uml:package"xmi.id="_9_0_bc102e5_1427365805826_580042_22" name="migration_s8ir2">
<packagedElement xmi:type="uml:Class"xmi.id="_9_0_bc102e5_1427367042666_255023_151" name="Employee">
<generalization xmi.id="_9_0_bc102e5_1427367042666_255023_151">
<general xmi:type="uml:Class" />
</generalization>
<ownedAttribute xmi.id="_9_0_bc102e5_1427367052819_893122_168"name="cin" />
</packagedElement>
<packagedElement xmi:type="uml:Class" xmi.id="_9_0_64701d4_1429716452808_363115_43" name="AssoEmpl">
<generalization xmi.id="_9_0_64701d4_1429716452808_363115_43">
<general xmi:type="uml:Class" />
</generalization>
</packagedElement>
</packagedElement>
</packagedElement>
</packagedElement>
</xmi:XMI>
最后是我的转换文件:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:UML="org.omg.xmi.namespace.UML"
xmlns:xmi="http://www.omg.org/XMI"
>
<xsl:output indent="yes" method="xml" />
<xsl:template match="/">
<xmi:XMI>
<xsl:attribute name="xmi.version">2.1</xsl:attribute>
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp" />
</xsl:attribute>
<xsl:for-each select="//UML:Package">
<packagedElement>
<xsl:attribute name="xmi:type">uml:package</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<xsl:choose>
<xsl:when test="UML:Class">
<xsl:for-each select="UML:Class">
<packagedElement>
<xsl:attribute name="xmi:type">uml:Class</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<generalization>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<general xmi:type="uml:Class" />
</generalization>
<xsl:for-each select="UML:Classifier.feature/UML:Attribute">
<ownedAttribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
</ownedAttribute>
</xsl:for-each>
</packagedElement>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</packagedElement>
</xsl:for-each>
</xmi:XMI>
</xsl:template>
</xsl:stylesheet>
我应该在转换代码中做什么来保持输入文件的层次结构?
当你这样做时:
<xsl:for-each select="//UML:Package">
您正在选择文档中的 所有 UML:Package
元素,任意位置,并将它们视为兄弟姐妹。由于这不是您想要的,因此您需要更改方法并改为递归应用模板。
我已经对您现有的样式表进行了快速调整,看看是否适合您:
<xsl:stylesheet xmlns:UML="org.omg.xmi.namespace.UML" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xmi:XMI xmi.version="2.1">
<xsl:attribute name="xmi.version">2.1</xsl:attribute>
<xsl:attribute name="timestamp">
<xsl:value-of select="@timestamp"/>
</xsl:attribute>
<xsl:apply-templates/>
</xmi:XMI>
</xsl:template>
<xsl:template match="UML:Package">
<packagedElement>
<xsl:attribute name="xmi:type">uml:package</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="UML:Class">
<xsl:for-each select="UML:Class">
<packagedElement>
<xsl:attribute name="xmi:type">uml:Class</xsl:attribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<generalization>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<general xmi:type="uml:Class"/>
</generalization>
<xsl:for-each select="UML:Classifier.feature/UML:Attribute">
<ownedAttribute>
<xsl:attribute name="xmi.id">
<xsl:value-of select="@xmi.id"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
</ownedAttribute>
</xsl:for-each>
</packagedElement>
</xsl:for-each>
</xsl:when>
</xsl:choose>
<xsl:apply-templates/>
</packagedElement>
</xsl:template>
</xsl:stylesheet>
注意:
您应该了解如何将属性直接添加到文字结果元素,以及如何使用属性值模板。这可以大大简化您的样式表。
这个:
<xsl:attribute name="timestamp"> <xsl:value-of select="@timestamp"/> </xsl:attribute>
在根节点的上下文中没有任何意义 属性.
如果您想要 推送式 类型的样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:UML="org.omg.xmi.namespace.UML"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xmi="http://www.omg.org/XMI">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" method="xml" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="XMI">
<xmi:XMI xmlns:xmi="http://www.omg.org/XMI" xmlns:UML="org.omg.xmi.namespace.UML"
xmi.version="2.1" timestamp="">
<xsl:apply-templates/>
</xmi:XMI>
</xsl:template>
<xsl:template match="UML:Package">
<packagedElement xmi:type="umi:package">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</packagedElement>
</xsl:template>
<xsl:template match="UML:Class">
<packagedElement xmi:type="uml:Class">
<xsl:copy-of select="@*"/>
<xsl:choose>
<xsl:when test="UML:Classifier.feature">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<generalization xmi.id="{../@xmi.id}">
<general xmi:type="uml:Class" />
</generalization>
</xsl:otherwise>
</xsl:choose>
</packagedElement>
</xsl:template>
<xsl:template match="UML:Classifier.feature">
<generalization xmi.id="{../@xmi.id}">
<general xmi:type="uml:Class" />
</generalization>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="UML:Attribute">
<ownedAttribute>
<xsl:copy-of select="@*"/>
</ownedAttribute>
</xsl:template>
<xsl:template match="XMI.content|UML:Model|UML:Namespace.ownedElement">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="UML:Generalization"/>
</xsl:stylesheet>