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

查看:29
本文介绍了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:

添加文本、注释、pi 或子元素节点后,无法将属性和命名空间节点添加到父元素."

假设我有这个简单的 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 以检索相关的 节点,例如2013 年.然后我需要使用 postid 对其子 节点进行降序排序,因此对于 ,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.

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

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="">)?通过研究,一个答案说我需要在元素创建之前添加属性创建".这在观察调试器时是有意义的,子节点按降序排列,但年份标记缺少其属性.但我对 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 文档的一部分(一个 节点)传递给 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天全站免登陆