Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XPath获取具有匹配子节点的节点以及其他子节点的最大值_Xml_Xslt_Xpath_Xslt 1.0 - Fatal编程技术网

Xml XPath获取具有匹配子节点的节点以及其他子节点的最大值

Xml XPath获取具有匹配子节点的节点以及其他子节点的最大值,xml,xslt,xpath,xslt-1.0,Xml,Xslt,Xpath,Xslt 1.0,我需要XPath 1.0中的帮助来过滤下面的XML,以便只获得具有不同“id”和最高“有效性/日期”的条: <foo name="fooName"> <bar name="barName"> <id>1111</id> <validity> <date>20170920</date> </validity> <

我需要XPath 1.0中的帮助来过滤下面的XML,以便只获得具有不同“id”和最高“有效性/日期”的条:

<foo name="fooName">
    <bar name="barName">
        <id>1111</id>
        <validity>
            <date>20170920</date>
        </validity>
    </bar>
    <bar name="barName">
        <id>1111</id>
        <validity>
            <date>20170922</date>
        </validity>
    </bar>
    <bar name="barName">
        <id>1111</id>
        <validity>
            <date>20170921</date>
        </validity>
    </bar>
    <bar name="barName">
        <id>2222</id>
        <validity>
            <date>20170921</date>
        </validity>
    </bar>
    <bar name="barName">
        <id>2222</id>
        <validity>
            <date>20170923</date>
        </validity>
    </bar>
</foo>
我尝试了很多选择和研究,但没有找到确切的解决方案

筛选后的预期XML应如下所示:

<foo name="fooName">
    <bar name="barName">
        <id>1111</id>
        <validity>
            <date>20170922</date>
        </validity>
    </bar>
    <bar name="barName">
        <id>2222</id>
        <validity>
            <date>20170923</date>
        </validity>
    </bar>
</foo>

你应该仔细阅读一下明钦教的分组,michael.hor257k已经给了你一个指针。网络搜索会找到很多其他的

穆钦族的做法是让你在原则上不用它的情况下能做的更快。在某些情况下,增加的速度使“原则上可行”和“实践上可行”之间存在差异。但在某些情况下,简单地解决这个问题就足够了

问题1:对于每个不同的“ID”,在输出中只需要一个“bar”元素。请注意,您的示例输出表明您的描述是错误的:您不希望只使用具有唯一“id”的条,因为id为1111或2222的条在输入中都没有唯一的id。您希望“id”的每个不同值都有一个单独的输出。不一样

解决此问题的一种方法是:为“bar”编写两个模板,一个模板在给定“id”的第一次出现时触发,并实际执行查找最大有效期/日期值的工作,另一个模板导致忽略所有随后出现的具有该“id”的“bar”

<xsl:template match="bar" priority="10.0">
   <!--* find the highest validity/date with this ID here,
       * do what needs to be done. *-->
   ...
</xsl:template>
<xsl:template match="bar[id = preceding-sibling::bar/id]"
              priority="20.0"/>
并简单地将当前值与它进行比较:

<xsl:when test="validity/date = $maxdate">
  <xsl:copy-of select="."/>
</
但是XPath 1.0中唯一的聚合函数是count和sum。我想说,看看XSLT2.0中这有多容易?但是如果你是在2.0中,整个事情就会是这样的

<xsl:sequence select="for $v in distinct-values(//bar/id)
    for $max in max(//bar[id=$v]/validity/date)
    return //bar[id=$v and validity/date = $max]"/>

max函数在使事情变得更简单方面起着相对温和的作用。]

正如我所建议的,我提出了下面的xslt,它似乎工作得很好:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:key name="bars-by-id" match="foo/bar" use="id" />
    <xsl:template match="foo">
        <foo name="fooName">
            <xsl:for-each select="bar[count(. | key('bars-by-id', id)[1]) = 1]">
                <xsl:variable name="currentID" select="id" />
                <xsl:variable name="barsForID" select="key('bars-by-id', $currentID)"/>
                <xsl:copy-of select="$barsForID[not(../bar[id=$currentID]/validity/date > validity/date)]" />
            </xsl:for-each>
        </foo>
    </xsl:template>
</xsl:stylesheet>

谢谢你的建议,真的很有帮助。请随时纠正我

这基本上是一个分组问题-请参阅:在每个组中,按日期排序并输出第一条或最后一条记录。@michael.hor257k谢谢。我将进一步探讨Muenchian分组。XSLT1.0中没有max函数。完全正确。我最初的回答有错误。现在修复。。。除非我只是替换了一个不同的错误,否则我希望在看到XSLT2.0有多简单之后可以使用它,但这是我无法控制的。谢谢你的解释。我的XML可以在30-50MB的范围内,所以我继续使用Muenchian分组。
<xsl:when test="validity/date = $maxdate">
  <xsl:copy-of select="."/>
</
<xsl:sequence select="for $v in distinct-values(//bar/id)
    for $max in max(//bar[id=$v]/validity/date)
    return //bar[id=$v and validity/date = $max]"/>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:key name="bars-by-id" match="foo/bar" use="id" />
    <xsl:template match="foo">
        <foo name="fooName">
            <xsl:for-each select="bar[count(. | key('bars-by-id', id)[1]) = 1]">
                <xsl:variable name="currentID" select="id" />
                <xsl:variable name="barsForID" select="key('bars-by-id', $currentID)"/>
                <xsl:copy-of select="$barsForID[not(../bar[id=$currentID]/validity/date > validity/date)]" />
            </xsl:for-each>
        </foo>
    </xsl:template>
</xsl:stylesheet>