使用 XSLT 将 XML 元素转换为 XML 属性
Posted
技术标签:
【中文标题】使用 XSLT 将 XML 元素转换为 XML 属性【英文标题】:Converting XML elements to XML attributes using XSLT 【发布时间】:2010-10-13 21:56:44 【问题描述】:我们有一个当前系统可以输出以下格式的 XML 文件:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
我需要使用这些数据加载到标准的 .NET 2.0 网格中。但是网格需要 XML 格式如下:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something">
</ITEM>
</INVENTORY>
即item的子节点需要转化为item节点的属性。
有人知道如何使用 XSLT 做到这一点吗?
【问题讨论】:
请阅读标记文档,您需要 4 个空格或一个制表符,以便 SO 识别代码。 你接受的答案不会产生你想要的结果!!!一个属性名称必须是“serialNumber”,接受的解决方案产生“serialnumber”。下次不要误导那些花时间提供帮助的人。 【参考方案1】:应该这样做:
<xsl:for-each select="//ITEM">
<xsl:element name="ITEM">
<xsl:attribute name="serialNumber">
<xsl:value-of select="SERIALNUMBER"/>
</xsl:attribute>
<xsl:attribute name="location">
<xsl:value-of select="LOCATION"/>
</xsl:attribute>
<xsl:attribute name="barcode">
<xsl:value-of select="BARCODE"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
或者使用大卫的快捷方式:
<xsl:for-each select="//ITEM">
<ITEM serialNumber="SERIALNUMBER" location="LOCATION" barcode="BARCODE"/>
</xsl:for-each>
【讨论】:
【参考方案2】:如果您的来源如下所示:
<row><a>1</a><b>2</b></row>
你希望它看起来像这样:
<row a="1" b="2" />
那么这个 XSLT 应该可以工作了:
<xsl:template match="row">
<row a="a" b="b" />
</xsl:template>
【讨论】:
【参考方案3】:这两个模板应该可以做到:-
<xsl:template match="ITEM">
<ITEM serialNumber="SERIALNUMBER" location="LOCATION" barcode="BARCODE" />
</xsl:template>
<xsl:template match="INVENTORY">
<INVENTORY>
<xsl:apply-templates />
</INVENTORY>
</xsl:template>
【讨论】:
【参考方案4】:这应该可行:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="INVENTORY">
<INVENTORY>
<xsl:apply-templates/>
</INVENTORY>
</xsl:template>
<xsl:template match="ITEM">
<ITEM>
<xsl:for-each select="*">
<xsl:attribute name="name()">
<xsl:value-of select="text()"/>
</xsl:attribute>
</xsl:for-each>
</ITEM>
</xsl:template>
</xsl:stylesheet>
【讨论】:
【参考方案5】:这可能是最简单的解决方案,它将ITEM
的任何子元素转换为其属性,并按原样复制其他所有内容,同时将元素名称转换为任何所需的属性名称:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!-- -->
<xsl:strip-space elements="*"/>
<xsl:variable name="vrtfNameMapping">
<item name="SERIALNUMBER" newName="serialNumber"/>
<item name="LOCATION" newName="location"/>
<item name="BARCODE" newName="barcode"/>
</xsl:variable>
<!-- -->
<xsl:variable name="vNameMapping" select=
"document('')/*/xsl:variable[@name='vrtfNameMapping']"/>
<!-- -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="ITEM/*">
<xsl:attribute name=
"$vNameMapping/*[@name=name(current())]/@newName">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
当上述转换应用于提供的 XML 文档时:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
产生想要的结果:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something"/>
</INVENTORY>
请注意以下几点:
identity rule的使用
<xsl:strip-space elements="*"/>
的使用
变量vrtfNameMapping
的使用没有任何xxx:node-set()
扩展函数。
事实上,我们处理名称和 newName 之间的任何映射,而不仅仅是简单的小写。
【讨论】:
看起来这种转换不起作用。它没有产生任何结果。就是这样:以上是关于使用 XSLT 将 XML 元素转换为 XML 属性的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python 或 XSLT 将复杂的 XML 转换为 CSV
使用 XSLT 将 XML 转换为 XML(添加、删除、修改)