简体   繁体   English

如何在子元素中按新计数值对元素进行排序。 XSLT 1.0

[英]How can I sort elements by new counted values in their child element. XSLT 1.0

I have an xml sheet of this kind: 我有一个这种xml表:

<houses>
    <house number="1">
        <mainroom>
            <roomprice>5</roomprice>
            <roomtax>2</roomtax>
        </mainroom>
        <roompricefull>
            <price value="8"/>
        </roompricefull>
    </house>
    <house number="2">
        <mainroom>
            <roomprice>3</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="7"/>
        </roompricefull>
    </house>
    <house number="3">
        <mainroom>
            <roomprice>9</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="4"/>
        </roompricefull>
    </house>
    <house number="4">
        <mainroom>
            <roomprice>12</roomprice>
            <roomtax>3</roomtax>
        </mainroom>
        <roompricefull>
            <price value="6"/>
        </roompricefull>
    </house>
</houses>

so I had to change the value of attribute "value" in "price" element in each of the "house" with the sum of "roomprice" value and "roomtax" 所以我不得不用“roomprice”值和“roomtax”之和改变每个“house”中“price”元素中属性“value”的值

I wrote an xsl transformation of such a kind: 我写了一个这样的xsl转换:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template name="PriceChange" match="price[parent::roompricefull]">
        <xsl:copy>
            <xsl:variable name="sn" select="../../@number"/>
            <xsl:variable name="TaxValue" select="number(//house[@number=string($sn)]/mainroom/roomtax)"/>
            <xsl:variable name="BaseValue" select="number(//house[@number=string($sn)]/mainroom/roomprice)"/>
            <xsl:attribute name="value">
                <xsl:value-of select="string($TaxValue+$BaseValue)"/>
            </xsl:attribute>
            <!--xsl:for-each select="/houses/house">
            <xsl:sort select="houses/house[$sn]/roompricefull/@value"/>
        </xsl:for-each-->
        </xsl:copy> 
    </xsl:template>
</xsl:stylesheet>

But when I started working on sorting "house" elements by my new value, I found problems. 但是当我开始按照我的新价值对“房子”元素进行排序时,我发现了问题。 I actually don't understand why it's not working, so I commented my last of the dozens examples in up code. 我实际上不明白为什么它不起作用,所以我在上面的代码中评论了我的最后几十个例子。

I got this: 我懂了:

<houses>
    <house number="1">
        <mainroom>
            <roomprice>5</roomprice>
            <roomtax>2</roomtax>
        </mainroom>
        <roompricefull>
            <price value="7"/>
        </roompricefull>
    </house>
    <house number="2">
        <mainroom>
            <roomprice>3</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="4"/>
        </roompricefull>
    </house>
    <house number="3">
        <mainroom>
            <roomprice>9</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="10"/>
        </roompricefull>
    </house>
    <house number="4">
        <mainroom>
            <roomprice>12</roomprice>
            <roomtax>3</roomtax>
        </mainroom>
        <roompricefull>
            <price value="15"/>
        </roompricefull>
    </house>
</houses>

But the expected result was: 但预期的结果是:

<houses>
    <house number="4">
        <mainroom>
            <roomprice>12</roomprice>
            <roomtax>3</roomtax>
        </mainroom>
        <roompricefull>
            <price value="15"/>
        </roompricefull>
    </house>   
    <house number="3">
        <mainroom>
            <roomprice>9</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="10"/>
        </roompricefull>
    </house>
    <house number="1">
        <mainroom>
            <roomprice>5</roomprice>
            <roomtax>2</roomtax>
        </mainroom>
        <roompricefull>
            <price value="7"/>
        </roompricefull>
    </house>
    <house number="2">
        <mainroom>
            <roomprice>3</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="4"/>
        </roompricefull>
    </house>
</houses>

It would be great if you could help me with sorting and explaining why my example is not working. 如果你可以帮我分类和解释为什么我的例子不起作用,那将是很棒的。 Seems that I don't understand the meaning of <sort/>, but everything I find tells me just about the usage of it without any explanation. 似乎我不理解<sort />的含义,但我找到的所有内容都告诉我关于它的用法而没有任何解释。 Thank you in advance. 先感谢您。

it would be great if you could help me with sorting 如果你可以帮我分类那就太棒了

This is the correct XSLT 1.0 approach. 这是正确的XSLT 1.0方法。

Notice the correct use of xsl:sort which needs: 注意正确使用xsl:sort需要:

  • the data-type to be specified, being string the default while we need here number 要指定的数据类型, 字符串是默认值,而我们需要这里的数字
  • the best use of sort inside the xsl:apply-templates xsl:apply-templates最好使用sort
  • the application of sorting with the sorting keys of the input document combined as required (sum). 排序的应用与输入文档的排序键组合在一起(总和)。
  • the sorting order also to be specified being the default ascending 排序顺序也指定为默认ascending

     <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="houses"> <xsl:copy> <xsl:apply-templates select="house"> <xsl:sort select="mainroom/roomprice + mainroom/roomtax" data-type="number" order="descending"/> </xsl:apply-templates> </xsl:copy> </xsl:template> <xsl:template match="price/@value"> <xsl:value-of select=" ../../../mainroom/roomprice + ../../../mainroom/roomtax"/> </xsl:template> 


explaining why my example is not working 解释为什么我的例子不起作用

Your transform does no work mainly because you are trying to sort elements in the wrong context (inside a template matching a deep child in the tree). 您的转换不起作用主要是因为您尝试在错误的上下文中对元素进行排序(在与树中的深子项匹配的模板内)。 Moreover: 此外:

  • you are trying to sort indicating a sorting key by absolute XPath pattern. 您正尝试按绝对XPath模式排序指示排序键。
  • you are not specifying the needed xsl:sort attributes 您没有指定所需的xsl:sort属性
  • you would like final elements be sorted according to a value calculated afterward and not present in the input document. 您希望最终元素根据之后计算的值排序,并且不会出现在输入文档中。 This is not the correct approach. 这不是正确的方法。 You must always use values present in the input document, eventually combining them properly. 您必须始终使用输入文档中存在的值,最终将它们正确组合。

Sort by the new price: 按新价格排序:

<xsl:template match="/">
  <xsl:for-each select="house">
    <xsl:sort select="mainroom/roomprice + mainroom/roomtax"/>
    <xsl:apply-templates select="."/>
  </xsl:for-each>
</xsl:template>

As before: 像之前一样:

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

Adjust the price in the output: 调整输出中的价格:

<xsl:template match="roompricefull">
  <roompricefull>
    <price value="{../mainroom/roomprice + ../mainroom/roomtax}"/>
  </roompricefull>
</xsl:template>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM