Xpath 2.0选择迭代的第一个和最后一个字符串

时间:2014-04-14 12:59:10

标签: xml xpath xpath-2.0

我有这棵树:

<Events>
 <Properties>
   <Property Descriptor=100>1378314022</Property>
   <Property Descriptor=200>ABC1234</Property>
 </Properties>
 <Properties>
   <Property Descriptor=100>1378314023</Property>
   <Property Descriptor=200>ABC1234</Property>
 </Properties>
 <Properties>
   <Property Descriptor=100>1378314024</Property>
   <Property Descriptor=200>ABC1234</Property>
 </Properties>
 <Properties>
   <Property Descriptor=100>1378314022</Property>
   <Property Descriptor=200>123456</Property>
 </Properties>
 <Properties>
   <Property Descriptor=100>1378314023</Property>
   <Property Descriptor=200>123456</Property>
 </Properties>
 <Properties>
   <Property Descriptor=100>1378314024</Property>
   <Property Descriptor=200>123456</Property>
 </Properties>

</Events>

我正在这个级别进行迭代:Events/Properties

我如何只有每个Property Descriptor = 200及其各自Property Descriptor = 100的第一次和最后一次出现?

到目前为止我已经尝试过了:

  • 迭代:Events/Properties
  • 选择: Property[@Descriptor=200])[last()] or Property[@Descriptor=200])[first()]

但没有成功。

OUTPUT应该看起来像这样[我用HTML显示它,在ROW级别迭代]:

P100        | P200
1378314022  | ABC1234
1378314024  | ABC1234
1378314022  | 123456
1378314024  | 123456

2 个答案:

答案 0 :(得分:3)

在XSLT 2.0中,使用for-each-group可以很容易,按200值分组并获取每个组的第一个和最后一个成员。但是在纯XPath(而不是XSLT)中,你需要横向思考。

如果这些组总是连续存在(即所有ABC1234条目彼此相邻,并且所有123456条目彼此相邻)那么这归结为希望每个Properties元素 P 没有前面的紧跟在后面的同级Properties元素200值为 P 。即你想迭代结束

Events/Properties[not(
  (
    Property[@Descriptor="200"] =
    preceding-sibling::Properties[1]/Property[@Descriptor="200"]
  ) and (
    Property[@Descriptor="200"] =
    following-sibling::Properties[1]/Property[@Descriptor="200"]
  )
)]

然后从每个生成的Property[@Descriptor="100"]元素中选择 Property[@Descriptor="200"]Properties

您已将问题标记为“xpath-2.0”,但此表达式在XPath 1.0中也有效。

答案 1 :(得分:0)

我不完全确定你要找的答案,但在这里我会举两个例子。其中一个应该可能符合您的需求。

我使用了以下输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<Events>
    <Properties>
        <Property Descriptor="100">1378314022</Property>
        <Property Descriptor="200">ABC1234</Property>
        <Property Descriptor="100">MD2356</Property>
        <Property Descriptor="200">25689</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314023</Property>
        <Property Descriptor="200">ABC1234</Property>
        <Property Descriptor="100">MD2356</Property>
        <Property Descriptor="200">25689</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314024</Property>
        <Property Descriptor="200">ABC1234</Property>
        <Property Descriptor="100">MD2356</Property>
        <Property Descriptor="200">25689</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314022</Property>
        <Property Descriptor="200">123456</Property>
        <Property Descriptor="100">MD2356</Property>
        <Property Descriptor="200">25689</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314023</Property>
        <Property Descriptor="200">123456</Property>
        <Property Descriptor="100">MD2356</Property>
        <Property Descriptor="200">25689</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314024</Property>
        <Property Descriptor="200">123456</Property>
        <Property Descriptor="100">MD2356</Property>
        <Property Descriptor="200">25689</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
</Events>

当我使用下一个XSLT时:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

    <xsl:template match="Properties">
        <xsl:copy>
            <xsl:apply-templates select="Property[@Descriptor = '100'][1]" />
            <xsl:apply-templates select="Property[@Descriptor = '100'][last()]" />
            <xsl:apply-templates select="Property[@Descriptor = '200'][1]" />
            <xsl:apply-templates select="Property[@Descriptor = '200'][last()]" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

此XSLT还对Properties元素进行了迭代,在Properties元素内,它获得了每个提供的Descriptor的第一个和最后一个元素。结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<Events>
    <Properties>
        <Property Descriptor="100">1378314022</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">ABC1234</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314023</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">ABC1234</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314024</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">ABC1234</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314022</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">123456</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314023</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">123456</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
    <Properties>
        <Property Descriptor="100">1378314024</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">123456</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
</Events>

如果你想在所有Properties上获得最后一次出现,那么XSLT应该略有不同:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

    <xsl:template match="Events">
        <xsl:copy>
            <Properties>
                <xsl:apply-templates select="(Properties/Property[@Descriptor = '100'])[1]" />
                <xsl:apply-templates select="(Properties/Property[@Descriptor = '100'])[last()]" />
                <xsl:apply-templates select="(Properties/Property[@Descriptor = '200'])[1]" />
                <xsl:apply-templates select="(Properties/Property[@Descriptor = '200'])[last()]" />
            </Properties>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<Events>
    <Properties>
        <Property Descriptor="100">1378314022</Property>
        <Property Descriptor="100">MD75632</Property>
        <Property Descriptor="200">ABC1234</Property>
        <Property Descriptor="200">5632</Property>
    </Properties>
</Events>