我的问题基于此:How to create XML nodes with attributes from Table
OP要求有机会使用动态创建的元素名称创建XML。
对于这个问题,XML的生成并不重要(但可能会在原始帖子中进行跟踪)。
此XML
<NodeA>
<NodeB></NodeB>
<NodeC AttributeX="">
<Row NodeName="RowA" AttributeA="" AttributeB="abcd" AttributeC="efgh" />
<Row NodeName="RowB" AttributeA="wxyz" />
<Row NodeName="RowC" AttributeB="qwer" AttributeC="tyui" />
<Row NodeName="RowD" AttributeA="stuv" AttributeB="erty" AttributeC="fghj" />
</NodeC>
</NodeA>
应转换为:
<NodeA>
<NodeB/>
<NodeC AttributeX="">
<RowA AttributeA="" AttributeB="abcd" AttributeC="efgh"/>
<RowB AttributeA="wxyz"/>
<RowC AttributeB="qwer" AttributeC="tyui"/>
<RowD AttributeA="stuv" AttributeB="erty" AttributeC="fghj"/>
</NodeC>
</NodeA>
唯一的区别是,&#34; Row&#34;元素的名称被&#34; NodeName&#34;的属性值替换。和属性&#34; NodeName&#34;本身就消失了。
在original post中我提出了一种XSLT方法(Can be tested here),它起作用但在我看来很复杂。有没有更好的方法来实现这一目标?
答案 0 :(得分:3)
您应该首先使用身份模板,该模板本身将复制所有节点和属性
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
然后,您可以从要更改的节点添加模板;在具有Row
属性的NodeName
元素中。或者也许可以转换任何具有NodeName
的元素。在这种情况下,模板匹配是这样的:
<xsl:template match="*[@NodeName]">
此模板的优先级高于身份模板,因此将首先进行匹配。有一点需要注意的是,在您链接到的问题中,模板匹配“*”,另一个匹配“node()”。这两者具有相同的优先级,这被认为是错误。 XSLT处理器可以标记错误,也可以选择最后一个模板。 (见https://www.w3.org/TR/xslt#conflict)
无论如何,在模板中,您可以创建一个名为NodeName
属性的新元素
<xsl:element name="{@NodeName}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
除此之外,您只需要另一个模板来确保NodeName
属性本身无法输出。
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@NodeName]">
<xsl:element name="{@NodeName}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@NodeName" />
</xsl:stylesheet>