使用 XSLT 将 XML 元素转换为 XML 属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/655411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting XML elements to XML attributes using XSLT
提问by eMTeeN
We have a current system that outputs an XML file which is in the following format:
我们有一个当前的系统,它输出一个 XML 文件,其格式如下:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
I need to use this data to load into the standard .NET 2.0 grid. But the grid needs the XML to be in the following format:
我需要使用这些数据加载到标准 .NET 2.0 网格中。但是网格需要采用以下格式的 XML:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something">
</ITEM>
</INVENTORY>
i.e. the child nodes of item need to be converted into attributes of the item node.
即item的子节点需要转换为item节点的属性。
Does someone know how this can be done using XSLT?
有人知道如何使用 XSLT 做到这一点吗?
回答by Johannes Weiss
That should work:
那应该工作:
<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>
HTH
HTH
回答by Dimitre Novatchev
Here is probably the simplest solutionthat will convert any children-elements of ITEMto its attributes and will reproduce everything else as is, while converting the element names to any desired attribute names:
这可能是最简单的解决方案,它将 的任何子元素转换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>
when the above transformation is applied on the provided XML document:
当上述转换应用于提供的 XML 文档时:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
the wanted result is produced:
产生了想要的结果:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something"/>
</INVENTORY>
Do notethe following:
请注意以下几点:
The use of the identity rule
The use of
<xsl:strip-space elements="*"/>The use of the variable
vrtfNameMappingwithout anyxxx:node-set()extension function.The fact that we handle any mapping between a name and a newName, not only simple lower-casing.
身份规则的使用
指某东西的用途
<xsl:strip-space elements="*"/>该变量的使用
vrtfNameMapping无需任何xxx:node-set()扩展功能。我们处理 name 和 newName 之间的任何映射的事实,而不仅仅是简单的小写。
回答by AnthonyWJones
These two templates should do it:-
这两个模板应该这样做:-
<xsl:template match="ITEM">
<ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}" />
</xsl:template>
<xsl:template match="INVENTORY">
<INVENTORY>
<xsl:apply-templates />
</INVENTORY>
</xsl:template>
回答by Welbog
This ought to do it:
这应该这样做:
<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>
Or using David's shortcut:
或者使用大卫的快捷方式:
<xsl:for-each select="//ITEM">
<ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}"/>
</xsl:for-each>
回答by David
If your source looks like this:
如果您的来源如下所示:
<row><a>1</a><b>2</b></row>
and you want it to look like this:
你希望它看起来像这样:
<row a="1" b="2" />
then this XSLT should work:
那么这个 XSLT 应该可以工作:
<xsl:template match="row">
<row a="{a}" b="{b}" />
</xsl:template>

