XSLT排序-如何在具有属性的父节点内对xml子节点进行排序 [英] XSLT Sorting - how to sort xml childnodes inside a parent node with an attribute

查看:89
本文介绍了XSLT排序-如何在具有属性的父节点内对xml子节点进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于XSLT菜鸟来说,一开始很简单的事情就变得非常麻烦.

What started out as a simple thing has turned out quite troublesome for XSLT noob.

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

Trying to sort childnodes/descending but, after adding an attribute to their parent node, I receive an error when debugging in 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:

Suppose I have this simple 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>

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

I pass a XPATH to a xmldatasource to retrieve the relevant <year> node, e.g. 2013. Then I need to sort its child <post> nodes descending using postid, so for <year value=2013>, postid=10050 would show up first when rendered.

因此,要明确一点:我只对在一个<year>节点内排序感兴趣.

So, to be clear: I'm only interested in sorting inside one <year> node.

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

Before I split the nodes into separate nodes (i.e. xml was /posts/post) the following XSLT worked:

<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>

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

Now the xmldatasource is empty when running due to the above error. If I pass ascending into the order the same xml is returned obviously (no transformation)

问题:如何更新上面的XSLT(或新版本)以适应父节点属性(<year value="">)?通过研究,一个回答说我需要在元素创建之前添加属性创建".在观察调试器时,这是有意义的,子节点按desc顺序形成,但是year标记缺少其属性.但是我对XSLT并不了解.看不出它太复杂,只是不懂语言.

Question: how to update the XSLT above (or new) to accommodate the parent node attribute (<year value="">)? Through research, an answer said "I need to added attribute creation before element creation". This makes sense as watching the debugger, the childnodes are formed in desc order, but the year tag is missing its attribute. But I don't have a clue really about XSLT. Can't see it being too complicated but just don't know the language.

任何帮助,我们将不胜感激.谢谢

Any help, greatly appreciated. Thanks

推荐答案

那么,您是说您只是将XML文档的一部分(一个<year>节点)传递给XSLT处理器吗?

So are you saying that you're only passing part of your XML document (one <year> node) to the XSLT processor?

您应该为年份使用一个单独的模板,因此这是唯一使用排序的模板.情况如何:

You should use a separate template for year, so that that's the only template that uses sorting. How is the following:

<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>

我认为上述方法是一种更好的方法,但我认为导致您的错误的根本原因是,在进行排序时,它会将属性与元素混合在一起.如果仅执行此操作,则原始XSLT可能会正确运行:

I think the above is a better approach, but I think the root cause of your error is that it was mingling the attributes in with the elements when it did the sorting. Your original XSLT probably would run without error if you simply did this:

<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>

这篇关于XSLT排序-如何在具有属性的父节点内对xml子节点进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆