我正在尝试转换输入XML,在该输入XML中,需要提取所有父节点说“ x”,对其进行排序,然后根据其子节点说“ y”的值在最终输出XML中重新排序。下面是我的XML,我正在尝试对其进行修改,以便最终的XML将具有按升序排列的元素,其中根据xpath中的数值notes/notesBODY/group/text
(基本上是<text>1. </text>
所有notes
元素中存在的元素)进行排序。但是输出XML并没有预期的那样,因为我似乎无法弄清楚如何在XSLT中准确地使用排序。任何帮助表示赞赏。
输入XML:
<root>
<group>
<text>group1</text>
</group>
<group>
<text>group2</text>
</group>
<notes>
<notesText>notes1</notesText>
<notesBODY>
<group>
<text>2. </text>
<text>notesbody1</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes2</notesText>
<notesBODY>
<group>
<text>1. </text>
<text>notesbody2</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes3</notesText>
<notesBODY>
<group>
<text>3. </text>
<text>notesbody3</text>
</group>
</notesBODY>
</notes>
<group>
<text>group3</text>
<notes>
<notesText>notes4</notesText>
<notesBODY>
<group>
<text>4. </text>
<text>notesbody4</text>
</group>
</notesBODY>
</notes>
</group>
<group>
<text>group4</text>
</group>
<group>
<text>group5</text>
<notes>
<notesText>notes5</notesText>
<notesBODY>
<group>
<text>6. </text>
<text>notesbody5</text>
</group>
</notesBODY>
</notes>
</group>
<notes>
<notesText>notes6</notesText>
<notesBODY>
<group>
<text>5. </text>
<text>notesbody6</text>
</group>
</notesBODY>
</notes>
<group>
<text>group6</text>
</group>
<group>
<text>group7</text>
</group>
<group>
<text>group8</text>
<notes>
<notesText>notes7</notesText>
<notesBODY>
<group>
<text>8. </text>
<text>notesbody7</text>
</group>
</notesBODY>
</notes>
</group>
<notes>
<notesText>notes8</notesText>
<notesBODY>
<group>
<text>7. </text>
<text>notesbody8</text>
</group>
</notesBODY>
</notes>
<group>
<text>group9</text>
</group>
</root>
预期产量:
<root>
<group>
<text>group1</text>
</group>
<group>
<text>group2</text>
</group>
<group>
<text>group3</text>
</group>
<group>
<text>group4</text>
</group>
<group>
<text>group5</text>
</group>
<group>
<text>group6</text>
</group>
<group>
<text>group7</text>
</group>
<group>
<text>group8</text>
</group>
<group>
<text>group9</text>
</group>
<notes>
<notesText>notes2</notesText>
<notesBODY>
<group>
<text>1. </text>
<text>notesbody2</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes1</notesText>
<notesBODY>
<group>
<text>2. </text>
<text>notesbody1</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes3</notesText>
<notesBODY>
<group>
<text>3. </text>
<text>notesbody3</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes4</notesText>
<notesBODY>
<group>
<text>4. </text>
<text>notesbody4</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes6</notesText>
<notesBODY>
<group>
<text>5. </text>
<text>notesbody6</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes5</notesText>
<notesBODY>
<group>
<text>6. </text>
<text>notesbody5</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes8</notesText>
<notesBODY>
<group>
<text>7. </text>
<text>notesbody8</text>
</group>
</notesBODY>
</notes>
<notes>
<notesText>notes7</notesText>
<notesBODY>
<group>
<text>8. </text>
<text>notesbody7</text>
</group>
</notesBODY>
</notes>
</root>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="notes">
<xsl:apply-templates select="@*" />
<xsl:copy>
<xsl:apply-templates select="node()">
<xsl:sort select="notesBODY/group/text[position() = 0]" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我想你基本上想使用两个模板
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="group"/>
<xsl:apply-templates select=".//notes">
<xsl:sort select="notesBODY/group/text[1]"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="group">
<xsl:copy>
<xsl:apply-templates select="* except notes"/>
</xsl:copy>
</xsl:template>
加上你已经拥有的身份转换。
@ Martin Honnen,但是我尝试了多近,因为我提供的模拟输入xml非常适合您的解决方案来对节点进行排序。对于我的实际输入xml,我做了一些细微的更改,而不是<xsl:template match =“ root”>,而是使用了<xsl:template match =“ /”>,然后对'notes'进行了完美排序,谢谢!但是,所有其他输入XML标记都将被删除,我的实际输入xml在根级别还具有许多其他标记。它还在组和注释级别具有属性。我曾以为身份模板可以处理这种情况,但看起来并非如此。你能建议吗?
@ Martin Honnen,我还注意到最终输出中缺少“ xml”标签的属性,就像我的实际xml中一样,我该如何复制这些属性?
如果有一个属性
group
或root
您需要使用<xsl:copy><xsl:apply-templates select="@*"/>...</xsl:copy>
(此处...
是上面代码中显示的属性)。我无法告诉您为什么您认为需要更改模板的匹配项,但期望代码执行相同的工作,或者将其作为一个单独的问题提出来。@ Martin Honnen,我用
<xsl:copy-of select="@*" />
代替,<xsl:apply-templates select="@*"/>
但它决定保留属性。这还可以使用吗?对于我发现的模板匹配,使用错了"\"
,我使用了group
节点的父节点,效果很好!如果您知道只需要复制属性,那当然
xsl:copy-of
就可以了,在apply-templates
使用身份转换作为基本模板的情况下,它的用途更加广泛,一旦需要更改属性,您只需添加一个模板那样做。