如果属性不存在,如何选择属性或回退值?

时间:2011-10-27 14:20:26

标签: xpath

我正在尝试计算与查询匹配的每个元素的特定属性(例如@root)的每个值的出现次数。其中一些匹配元素没有属性,但我也要计算它们(也就是列出没有属性的匹配元素的数量)

目前我使用它,但这与没有root属性的节点不匹配。计数由应用程序完成,这允许我显示中间结果。

    //node[@rel='su']/@root

我想要像

这样的东西
    //node[@rel='su']/string(if .[@root] then @root else 'fallback-value')

查询是针对Berkeley DB XML运行的,因此XPath2和XQuery也可能用于解决此问题。

编辑:为了澄清,我正在寻找一个查询,它将@root属性的不存在视为一种特殊情况;即好像该属性确实存在并且具有'后备值'作为值。

4 个答案:

答案 0 :(得分:1)

试试这个:

//node[@rel='su']/(@root/string(), 'no-value')[1]

遵循误解问题的原始答案

为什么不使用

//node[@rel='su']

然后?它将匹配具有node属性的@root元素和不具有node属性的元素。

鉴于@root最多只能有一个{{1}}属性,计算节点就足够了。

答案 1 :(得分:1)

这可以使用XQuery轻松完成。首先,在执行备用策略时收集匹配值:

   let $matches := //node[@rel='su']/(data(@root), '')[1]

以上是对您问题中所表达的表达的略微纠正的重新表述。但请注意,它将使用零长度值处理根属性,与非现有根属性相同。

然后按不同的值进行分组,并计算每个组的出现次数:

   for $value in distinct-values($matches)
   let $count := count($matches[. = $value])
   return <value count="{$count}">{$value}</value>

当应用于此输入时,

  <x>
    <node rel="su" root="A"/>
    <node rel="su" root="A"/>
    <node rel="su" root="B"/>
    <node rel="su" root=""/>
    <node rel="su"/>
    <node rel="su"/>
  </x>

结果可能是

  <value count="2">A</value>
  <value count="1">B</value>
  <value count="3"/>

要强制执行结果的特定顺序,请添加order by子句:

  for $value in distinct-values($matches)
  let $count := count($matches[. = $value])
  order by $value
  return <value count="{$count}">{$value}</value>

答案 2 :(得分:0)

这个怎么样?

//node[@rel='su' and not(@root)]

这应匹配没有root属性的节点。

答案 3 :(得分:0)

使用

concat('Having @root: ', count(//node[@rel='su']/@root ),
       ', Not having @root: ', count(//node[@rel='su'][not(@root)]),
       ', Having @root occur ',
       floor(count(//node[@rel='su']/@root ) div count(//node[@rel='su']) * 100),
       '% of the time.'
       )

基于XSLT的验证

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:value-of select=
  "concat('Having @root: ', count(//node[@rel='su']/@root ),
          ', Not having @root: ', count(//node[@rel='su'][not(@root)]),
          ', Having @root occur ',
          floor(count(//node[@rel='su']/@root ) div count(//node[@rel='su']) * 100),
          '% of the time.'
         )
  "/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档

<t>
 <node rel="su" root="2"/>
 <node rel="su" root="1"/>
 <node rel="su" />
 <node rel="su" root="4"/>
 <node rel="su" root="5"/>
 <node rel="su"  />
 <node rel="su" root="7"/>
 <node rel="su" root="8"/>
 <node rel="su" />
 <node rel="su" />
</t>

产生了想要的正确结果

Having @root: 6, Not having @root: 4, Having @root occur 60% of the time.