我有以下XML
<Root>
<Element A/>
<Element B/>
<Data1>
<DataElement/>
<Values>
<Value>2222</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>ABC</Value>
<Name>field2</Name>
</Values>
</Data1>
<Data2>
<DataElement/>
<Values>
<Value>1111</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>XYZ</Value>
<Name>field2</Name>
</Values>
</Data2>
<DataN>
...
</DataN>
</Root>
我需要获取与指定字段名称的“值”排序的数据部分相同的XML,例如: 按“field1”排序将返回
<Root>
<Element A/>
<Element B/>
<Data2>
<DataElement/>
<Values>
<Value>1111</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>XYZ</Value>
<Name>field2</Name>
</Values>
</Data2>
<Data1>
<DataElement/>
<Values>
<Value>2222</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>ABC</Value>
<Name>field2</Name>
</Values>
</Data1>
<DataN>
...
</DataN>
</Root>
另外,我必须将sort字段的名称作为参数...
发送答案 0 :(得分:2)
此转换完全符合规定的要求。需要特别注意保留不要排序的元素的确切顺序。目前没有其他答案:
<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:param name="vField" select="'field1'"/>
<xsl:param name="pSortType" select="'number'"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(name(),'Data')]">
<xsl:variable name="vPos" select=
"count(preceding-sibling::*[starts-with(name(),'Data')])+1"/>
<xsl:for-each select="/*/*[starts-with(name(),'Data')]">
<xsl:sort select="Values[Name=$vField]/Value"
data-type="{$pSortType}"/>
<xsl:if test="position() = $vPos">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
应用于以下XML文档(与提供的文档相同,但在<Element C=""/>
和Data1
之间插入了额外的Data2
,以便我们可以验证保存未排序元素的排序):
<Root>
<Element A=""/>
<Element B=""/>
<Data1>
<DataElement/>
<Values>
<Value>2222</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>ABC</Value>
<Name>field2</Name>
</Values>
</Data1>
<Element C=""/>
<Data2>
<DataElement/>
<Values>
<Value>1111</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>XYZ</Value>
<Name>field2</Name>
</Values>
</Data2>
</Root>
生成想要的正确结果 - 请注意保留<Element C=""/>
的位置:
<Root>
<Element A=""/>
<Element B=""/>
<Data2>
<DataElement/>
<Values>
<Value>1111</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>XYZ</Value>
<Name>field2</Name>
</Values>
</Data2>
<Element C=""/>
<Data1>
<DataElement/>
<Values>
<Value>2222</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>ABC</Value>
<Name>field2</Name>
</Values>
</Data1>
</Root>
答案 1 :(得分:0)
我认为你可以采用这种简单的转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="field" select="'field1'"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Root">
<xsl:copy>
<xsl:apply-templates select="@*|*">
<xsl:sort select="Values[Name=$field]/
Value[string(number(.))!='NaN']"
data-type="number"/>
<xsl:sort select="Values[Name=$field]/
Value[string(number(.))='NaN']"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于您的输入时(已更正以使其格式正确):
<Root>
<Element A=""/>
<Element B=""/>
<Data1>
<DataElement/>
<Values>
<Value>2222</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>ABC</Value>
<Name>field2</Name>
</Values>
</Data1>
<Data2>
<DataElement/>
<Values>
<Value>1111</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>XYZ</Value>
<Name>field2</Name>
</Values>
</Data2>
</Root>
产生
<Root>
<Element A=""></Element>
<Element B=""></Element>
<Data2>
<DataElement></DataElement>
<Values>
<Value>1111</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>XYZ</Value>
<Name>field2</Name>
</Values>
</Data2>
<Data1>
<DataElement></DataElement>
<Values>
<Value>2222</Value>
<Name>field1</Name>
</Values>
<Values>
<Value>ABC</Value>
<Name>field2</Name>
</Values>
</Data1>
</Root>
说明: