使用XPath从XML获取特定节点

时间:2011-11-12 10:40:51

标签: xml xslt xpath nodes

我有一个像这样的XML文档:

<food>
<fruit>
    <apple>
        <product>
            <title>Apple 1</title>
            <price>7</price>
        </product>

        <product>
            <title>Apple 2</title>
            <price>4</price>
        </product>
    </apple>

    <grapes>
        <product>
            <title>Red grapes </title>
            <price>4</price>
        </product>
        <product>
            <title>Green grapes</title>
            <price>6</price>
        </product>
    </grapes>
</fruit>
<drink>
    <water>
        <product>
            <title>Water 1</title>
            <price>1</price>
        </product>
        <product>
            <title>Water 2</title>
            <price>6</price>
        </product>
    </water>
    <soda>
        <product>
            <title>Coca-Cola</title>
            <price>10</price>
        </product>
        <product>
            <title>Sprite</title>
            <price>4</price>
        </product>
    </soda>
</drink>
</food>

我有这样的XML结构。

我想获取所有成本高于5的产品的产品名称和价格。如何编写执行此操作的XPath表达式?

2 个答案:

答案 0 :(得分:3)

我认为您的文档以</food>结尾。那是你要的吗 ?

//product[price > 5]

编辑:

如果您不想使用<product>标记,则可以执行此操作:

//product[price > 5]/*

但是,我发现最后一个解决方案不太方便,因为我们不再划分产品了。

答案 1 :(得分:2)

使用

  /*/*/*/product[price > 5]/title 
|
  /*/*/*/product/price[. > 5]

这将选择以下联合:

  1. 所有titleproduct个父元素,其price子元素的字符串值在被视为数字时大于5,它是顶级元素的曾孙XML文档。

  2. 所有price个元素,其字符串值在被视为数字时大于5,其父元素是product,它是XML文档顶级元素的曾孙

  3. 选择的元素以文档顺序(通常)以文档顺序提供,这意味着title及其对应的price在由节点集产生的任何节点集中彼此相邻相应的XPath API。

    在XSLT中,我们会使用这样一个非常简单的转换:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="product[price > 5]">
      Name: <xsl:value-of select="title"/>
      <xsl:text>, price </xsl:text>
      <xsl:value-of select="price"/>
     </xsl:template>
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    

    应用于提供的XML文档

    <food>
    <fruit>
        <apple>
            <product>
                <title>Apple 1</title>
                <price>7</price>
            </product>
    
            <product>
                <title>Apple 2</title>
                <price>4</price>
            </product>
        </apple>
    
        <grapes>
            <product>
                <title>Red grapes </title>
                <price>4</price>
            </product>
            <product>
                <title>Green grapes</title>
                <price>6</price>
            </product>
        </grapes>
    </fruit>
    <drink>
        <water>
            <product>
                <title>Water 1</title>
                <price>1</price>
            </product>
            <product>
                <title>Water 2</title>
                <price>6</price>
            </product>
        </water>
        <soda>
            <product>
                <title>Coca-Cola</title>
                <price>10</price>
            </product>
            <product>
                <title>Sprite</title>
                <price>4</price>
            </product>
        </soda>
    </drink>
    </food>
    

    产生了想要的正确结果

      Name: Apple 1, price 7
      Name: Green grapes, price 6
      Name: Water 2, price 6
      Name: Coca-Cola, price 10
    

    最好将价格限制指定为外部传递给转化的全局参数。

    在这种情况下,XSLT 2.0转换更简单一点:

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:param name="pLimit" select="5"/>
    
     <xsl:template match="product[price > $pLimit]">
      Name: <xsl:value-of select="title"/>
      <xsl:text>, price </xsl:text>
      <xsl:value-of select="price"/>
     </xsl:template>
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    

    相应的XSLT 1.0转换

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:param name="pLimit" select="5"/>
    
     <xsl:template match="product">
      <xsl:if test="price > $pLimit">
          Name: <xsl:value-of select="title"/>
          <xsl:text>, price </xsl:text>
          <xsl:value-of select="price"/>
      </xsl:if>
     </xsl:template>
     <xsl:template match="text()"/>
    </xsl:stylesheet>