我一直在努力解决一个需求,我需要对xml文档的一部分进行排序(而不是完整的树)。
<Root>
<AllData>
<Data_not_to_be_sorted>
<Additional_data1>
<Some_test_data1/>
<Some_test_data2/>
</Additional_data1>
</Data_not_to_be_sorted>
<RealData>
<Some_data1/>
<Some_data2/>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>4</Value>
<Name>name in 4</Name>
</Father>
</GrandFather>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>3</Value>
<Name>name in 3</Name>
</Father>
</GrandFather>
</RealData>
<RealData>
<Some_data1/>
<Some_data2/>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>2</Value>
<Name>name in 2</Name>
</Father>
</GrandFather>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>1</Value>
<Name>name in 1</Name>
</Father>
</GrandFather>
</RealData>
</AllData>
</Root>
所以在对父/值进行排序后,我应该得到正确的GrandFather序列
<Root>
<AllData>
<Data_not_to_be_sorted>
<Additional_data1>
<Some_test_data1/>
<Some_test_data2/>
</Additional_data1>
</Data_not_to_be_sorted>
<RealData>
<Some_data1/>
<Some_data2/>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>3</Value>
<Name>name in 3</Name>
</Father>
</GrandFather>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>4</Value>
<Name>name in 4</Name>
</Father>
</GrandFather>
</RealData>
<RealData>
<Some_data1/>
<Some_data2/>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>1</Value>
<Name>name in 1</Name>
</Father>
</GrandFather>
<GrandFather>
<Data_required_as_it_is></Data_required_as_it_is>
<Father>
<Value>2</Value>
<Name>name in 2</Name>
</Father>
</GrandFather>
</RealData>
</AllData>
</Root>
换句话说,我想基于父/值对子树GrandFather进行排序。休息一切都应该保持不变。我尝试过类似下面的内容..但这只是将源xml复制到输出中。
<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="*"/>
<!-- Template to copy the nodes as they are -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="GrandFather">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()">
<xsl:sort select="self::Father/Value" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
这种正确,更短,更简单,更通用的转型:
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[F]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()">
<xsl:sort select="self::F/Value" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<Root>
<AllData>
<Data_not_to_be_sorted>
<Additional_data1>
<Some_test_data1/>
<Some_test_data2/>
</Additional_data1>
</Data_not_to_be_sorted>
<data>
<Some_data1></Some_data1>
<Some_data2></Some_data2>
<F>
<Value>2</Value>
<Name>name in 2</Name>
</F>
<F>
<Value>1</Value>
<Name>name in 1</Name>
</F>
</data>
<data>
<Some_data1></Some_data1>
<Some_data2></Some_data2>
<F>
<Value>4</Value>
<Name>name 4</Name>
</F>
<F>
<Value>3</Value>
<Name>name in 3</Name>
</F>
</data>
</AllData>
</Root>
会产生想要的正确结果:
<Root>
<AllData>
<Data_not_to_be_sorted>
<Additional_data1>
<Some_test_data1/>
<Some_test_data2/>
</Additional_data1>
</Data_not_to_be_sorted>
<data>
<Some_data1/>
<Some_data2/>
<F>
<Value>1</Value>
<Name>name in 1</Name>
</F>
<F>
<Value>2</Value>
<Name>name in 2</Name>
</F>
</data>
<data>
<Some_data1/>
<Some_data2/>
<F>
<Value>3</Value>
<Name>name in 3</Name>
</F>
<F>
<Value>4</Value>
<Name>name 4</Name>
</F>
</data>
</AllData>
</Root>
答案 1 :(得分:0)
问题是F/Value
不是Root
的孩子。此外,在Root
下应用排序(如果您提供了可用的排序键)将仅对根的子元素进行排序。你需要做这样的事情(未经测试):
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="data">
<xsl:apply-templates select="Some_data1"/>
<xsl:apply-templates select="Some_data2"/>
<xsl:apply-templates select="F">
<xsl:sort select="Value"/>
</xsl:apply-templates>
</xsl:template>
关键是要记住样式表是声明性的,而不是程序性的。 XSLT引擎读取您的XML,并在每个输入元素处查看样式表以确定要输出的内容。