【问题标题】:XPath expression selecting element based on another node's value基于另一个节点的值的 XPath 表达式选择元素
【发布时间】:2013-03-03 12:36:56
【问题描述】:

使用以下 XML,是否可以使用 XPath 表达式选择本地项目元素,其中具有相同代码的区域项目金额在本地项目金额的 5% 以内?在此示例中,将选择本地项目 4。

<?xml version="1.0" encoding="UTF-8"?>

<Inventory> 
  <Local> 
    <Item> 
      <Code>1</Code>  
      <Amount>10000</Amount> 
    </Item>  
    <Item> 
      <Code>2</Code>  
      <Amount>20000</Amount> 
    </Item>  
    <Item> 
      <Code>3</Code>  
      <Amount>30000</Amount> 
    </Item>  
    <Item> 
      <Code>4</Code>  
      <Amount>40000</Amount> 
    </Item> 
  </Local>  
  <Regional> 
    <Item> 
      <Code>2</Code>  
      <Amount>100</Amount> 
    </Item>  
    <Item> 
      <Code>4</Code>  
      <Amount>39900</Amount> 
    </Item> 
  </Regional> 
</Inventory>

到目前为止,我只能使用下面的表达式选择具有相同代码的本地项目,该表达式返回两个元素,但我似乎无法弄清楚如何将两个元素乘以 0.95,因为添加了 "/Amount * 0.95" 到这个表达式的末尾会导致它只返回第一个项目的数量乘以 0.95。

/Inventory/Local/Item[Code=/Inventory/Regional/Item/Code]

【问题讨论】:

    标签: xml xpath xpath-2.0


    【解决方案1】:

    你可以试试xquery:

    XQuery

    for $x in doc("input.xml")//Local/Item
    let $y:=doc("input.xml")//Regional/Item[Code=$x/Code]
    where $y/Amount*0.95<=$x/Amount and $x/Amount<=$y/Amount*1.05
    return $x
    

    在 shell 中测试

    $ zorba -q 'for $x in doc("input.xml")//Local/Item let $y:=doc("input.xml")//Regional/Item[Code=$x/Code] where $y/Amount*0.95<=$x/Amount and $x/Amount<=$y/Amount*1.05 return $x'
    

    输出

    <?xml version="1.0" encoding="UTF-8"?>
    <Item> 
          <Code>4</Code>  
          <Amount>40000</Amount> 
    </Item>
    

    【讨论】:

      【解决方案2】:

      我发现这个问题很有趣,最近一个小时一直在尝试解决它,

      这是使用 XPATH 2.0 的解决方案:

      for $x  in   /Inventory/Local/Item[Code=/Inventory/Regional/Item/Code],
          $y   in   /Inventory/Regional/Item[Code = $x/code]
            return  $x[Amount div 20 <= $y/Amount ]
      

      很确定这不能使用 XPath 1.0 表达式来完成。

      【讨论】:

        【解决方案3】:

        不需要 XQuery 来指定所需的选择

        这是一个正确、更短且更高效的 XPath 2.0 表达式

        for $locItem in /*/Local/*,
            $locAmount in $locItem/Amount,
            $fivePercent in $locAmount*0.05,
            $regItem in
            /*/Regional/Item
                 [Code eq $locItem/Code
                and
                 abs(Amount -$locAmount) le $fivePercent
                 ]
         return $locItem
        

        基于 XSLT 2.0 的验证:

        <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:output omit-xml-declaration="yes" indent="yes"/>
        
         <xsl:template match="/">
          <xsl:sequence select=
           "for $locItem in /*/Local/*,
                $locAmount in $locItem/Amount,
                $fivePercent in $locAmount*0.05,
                $regItem in
                /*/Regional/Item
                     [Code eq $locItem/Code
                    and
                     abs(Amount -$locAmount) le $fivePercent
                     ]
             return $locItem"/>
         </xsl:template>
        </xsl:stylesheet>
        

        当此转换应用于提供的 XML 文档时:

        <Inventory>
          <Local>
            <Item>
              <Code>1</Code>
              <Amount>10000</Amount>
            </Item>
            <Item>
              <Code>2</Code>
              <Amount>20000</Amount>
            </Item>
            <Item>
              <Code>3</Code>
              <Amount>30000</Amount>
            </Item>
            <Item>
              <Code>4</Code>
              <Amount>40000</Amount>
            </Item>
          </Local>
          <Regional>
            <Item>
              <Code>2</Code>
              <Amount>100</Amount>
            </Item>
            <Item>
              <Code>4</Code>
              <Amount>39900</Amount>
            </Item>
          </Regional>
        </Inventory>
        

        计算 XPath 表达式,并将计算结果复制到输出:

        <Item>
            <Code>4</Code>
            <Amount>40000</Amount>
        </Item>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-14
          • 2012-09-23
          • 2017-02-19
          相关资源
          最近更新 更多