我的问题的更一般版本是recently posted,但由于帖子的质量,它没有收到回复。这是我的尝试!
我有以下要转换的XML结构
<schema>
<!-- element to be imbedded -->
<element name="tryCatch.catch">
<complexType>
<complexContent>
<extension base="escalateContainer">
<attribute name="var" type="_var" />
</extension>
</complexContent>
</complexType>
</element>
<complexType name="tryCatch">
<complexContent>
<extension base="scriptElement">
<sequence>
<element name="try" type="escalateContainer" />
<element name="catch" type="tryCatch.catch" minOccurs="0" />
<element name="finally" type="escalateContainer" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
...进入以下结构:
<schema>
<complexType name="tryCatch">
<complexContent>
<extension base="scriptElement">
<sequence>
<element name="try" type="escalateContainer" />
<!-- Change here! -->
<element name="tryCatch.catch" minOccurs="0">
<complexType>
<complexContent>
<extension base="escalateContainer">
<attribute name="var" type="_var" />
</extension>
</complexContent>
</complexType>
</element>
<element name="finally" type="escalateContainer" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
基本上,我只想
然后找到{em} 中element
complexType
的所有.
个孩子(通过构造 - 我确保此模式有效我的XML中的内容)。我的比赛的简化版本是:
complexType.element.type = element.name
最后,将该元素替换为相应的全局元素。如果要替换的元素上的属性也被复制,则加分。
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="schema">
<xsl:for-each select="element">
<xsl:variable name="self" select="current()" />
<xsl:variable name="name" select="@name" />
<xsl:for-each select="/schema/complexType//element[@type=$name]">
<xsl:copy-of select="$self" />
</xsl:for-each>
</xsl:for-each>
</xsl:template>
我认为我是正确的开始 - 使用身份模板复制所有内容,然后处理我想要更改的内容。问题是我的第二个模板仅返回复制的元素!这场比赛似乎很有效,我只是失去了我试图保留的所有其他内容。
答案 0 :(得分:4)
一般来说for-each
的使用并不是最好的主意。它使模板不灵活且难以阅读。 (当然有时你无法避免它,但在这种情况下它是可能的。)你应该使用apply-templates
将迭代留给XSLT引擎。我会做这样的事情:
<xsl:template match="@* | node()" priority="-1"> <!-- copy everything unless another template with higher priority says otherwise -->
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="schema">
<xsl:copy> <!-- copy the <schema> element -->
<xsl:apply-templates select="complexType"/> <!-- copy all complexType elements within schema -->
</xsl:copy>
</xsl:template>
<xsl:template match="element[contains(@type, '.')]"> <!-- if we encounter an <element> whose name contains the '.' character -->
<xsl:variable name="type" select="@type" />
<xsl:apply-templates select="//element[@name=$type]"/> <!-- copy the matching element instead -->
</xsl:template>
更新:我刚刚意识到我已将@type
与@name
混为一谈,修正了此问题。