XSLT排序 - 如何使用属性对父节点内的xml子节点进行排序

Jim*_*mXC 9 xml sorting xslt xpath xslt-grouping

对于XSLT noob来说,最简单的事情已经变得非常棘手.

尝试对子节点/降序进行排序,但在向父节点添加属性后,在VS2010中调试时收到错误:

"Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added."

假设我有这个简单的XML:

<posts>
    <year value="2013">
        <post postid="10030" postmonth="1">
            <othernode></othernode>
            <othernode2></othernode2>
        </post>
        <post postid="10040" postmonth="2">
            <othernode></othernode>
            <othernode2></othernode2>
        </post>
        <post postid="10050" postmonth="3">
             <othernode></othernode>
             <othernode2></othernode2>
        </post>
    </year>
    <year value="2012">
        <post postid="10010" postmonth="1">
            <othernode></othernode>
            <othernode2></othernode2>
        </post>
        <post postid="10015" postmonth="2">
            <othernode></othernode>
            <othernode2></othernode2>
        </post>
        <post postid="10020" postmonth="3">
             <othernode></othernode>
             <othernode2></othernode2>
        </post>
    </year>
</posts>
Run Code Online (Sandbox Code Playgroud)

我将XPATH传递给xmldatasource以检索相关<year>节点,例如2013.然后我需要<post>使用postid 对其子节点进行降序排序,因此<year value=2013>,postid = 10050将在渲染时首先显示.

所以,要明确:我只对在一个<year>节点内进行排序感兴趣.

在将节点拆分为单独的节点(即xml是/ posts/post)之前,以下XSLT工作:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()">
                <xsl:sort select="@postid" data-type="text" order="descending"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

现在,由于上述错误,xmldatasource在运行时为空.如果我将升序传递给顺序,则显然返回相同的xml(无转换)

问题:如何更新上面的(或新的)XSLT以容纳父节点属性(<year value="">)?通过研究,答案说"我需要在元素创建之前添加属性创建".这在观察调试器时是有意义的,子节点是按desc顺序形成的,但是year标签缺少其属性.但我真的没有关于XSLT的线索.看不到太复杂但只是不懂语言.

任何帮助,非常感谢.谢谢

JLR*_*she 9

所以你是说你只是将部分XML文档(一个<year>节点)传递给XSLT处理器?

您应该使用单独的年份模板,以便这是唯一使用排序的模板.如何:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="year">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:apply-templates select="post">
        <xsl:sort select="@postid" data-type="number" order="descending"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

我认为上面是一个更好的方法,但我认为你的错误的根本原因是它在进行排序时将元素与元素混合在一起.如果您只是这样做,您的原始XSLT可能会正常运行:

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*">
        <xsl:apply-templates select="node()">
            <xsl:sort select="@postid" data-type="text" order="descending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)