XPath表达式根据另一个节点的值选择元素

时间:2013-03-14 22:37:29

标签: xml xpath xpath-2.0

使用以下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]

3 个答案:

答案 0 :(得分:0)

您可以尝试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>

答案 1 :(得分:0)

我发现这个问题非常有趣,一直在努力解决这个问题,

这是使用 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表达式无法完成此操作。

答案 2 :(得分:0)

不需要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>