Как выбрать атрибут или запасное значение, если атрибут не существует? - PullRequest
2 голосов
/ 27 октября 2011

Я пытаюсь подсчитать вхождения каждого значения для определенного атрибута (например, @root) каждого элемента, соответствующего запросу. Некоторые из этих совпадающих элементов не имеют атрибута, но я также хочу их подсчитать (т. Е. Также указать количество совпадающих элементов, которые не имеют атрибута)

В настоящее время я использую это, но это не соответствует узлам, которые не имеют атрибута root. Подсчет выполняется приложением, которое позволяет мне показывать промежуточные результаты.

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

Я хочу что-то вроде

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

Запросы выполняются к Berkeley DB XML, поэтому XPath2 и XQuery также могут быть использованы для решения этой проблемы.

edit: чтобы уточнить, я ищу запрос, который рассматривает несуществование атрибута @root как особый случай; то есть как если бы атрибут существовал и имел в качестве значения «запасное значение».

Ответы [ 4 ]

1 голос
/ 28 октября 2011

Это легко сделать с помощью 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>
1 голос
/ 27 октября 2011

Попробуйте это:

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

Следует за первоначальным ответом на неправильно понятый вопрос

Почему бы вам просто не использовать

//node[@rel='su']

тогда? Он будет соответствовать как элементам node, которые имеют атрибут @root, так и элементам, которые не имеют.

Учитывая, что node может иметь не более одного @root атрибутов, достаточно подсчитать количество узлов.

0 голосов
/ 28 октября 2011

Используйте

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.
0 голосов
/ 27 октября 2011

А как насчет этого?

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

Это должно соответствовать узлам без атрибута root.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...