Xpath: сложное выражение, включающее некоторые узлы и исключающее другие - PullRequest
1 голос
/ 20 сентября 2011

Пример xml:

<foo>
    <bar name="bar1">
    </bar>
    <bar name="bar2">
    </bar>
</foo>
<qux>
    <foo>
        <bar name="bar3">
        </bar>
    </foo>
     <bar name="bar4">
     </bar>
</qux>

Каково выражение для выбора всех элементов bar, которые являются дочерними для корневого foo (bar1, bar2, bar4), но не для вложенного foo (bar3)?

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 20 сентября 2011

Каково выражение для выбора всех элементов бара, которые являются потомками корень foo (bar1, bar2, bar4), но не вложенный foo (bar3)?

Вот, вероятно, одно из самых простых и коротких выражений XPath , которое при оценке в любом правильно сформированном документе XML, который имеет верхний элемент foo и может иметь любой уровень вложенных элементов foo, выбирает в точности bar элементов, у которых единственный foo предок является верхним элементом:

//bar[not(ancestor::foo[2])]

Это выражение Xpath выбирает любой элемент bar в документе, который имеет менее двух foo предков. Поскольку по определению верхний элемент является foo, это означает, что каждый bar имеет этот верхний элемент foo в качестве предка. Если он находится во вложенном foo, он имеет по крайней мере второго предка foo и не будет выбран вышеприведенным выражением XPath, потому что в этом случае boolean(ancestor::foo[2]) равно true()

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:copy-of select=
   "//bar[not(ancestor::foo[2])]"/>
 </xsl:template>
</xsl:stylesheet>

при применении к следующему XML-документу (на основе предоставленного XML-фрагмента, но делая его правильно сформированным XML-документом и добавляя немного больше вложенности / сложности, чтобы сделать это интересным):

<foo>
    <bar name="bar1">
    </bar>
    <bar name="bar2">
    </bar>
    <qux>
        <foo>
           <baz>
             <bar name="bar3">
             </bar>
            </baz>
        </foo>
        <bar name="bar4">
        </bar>
        <qux>
            <foo>
                <bar name="bar5">
                </bar>
            </foo>
            <bar name="bar6">
            </bar>
        </qux>
    </qux>
</foo>

выводит именно нужные элементы :

<bar name="bar1">

</bar>
<bar name="bar2">

</bar>
<bar name="bar4">

</bar>
<bar name="bar6">

</bar>
1 голос
/ 20 сентября 2011

Как сказал @Cheeso, документ недействителен, и, похоже, он не совпадает с вашим вопросом.

Если это документ, который вы имели в виду (где qux находится внутри первого foo)

<foo>
    <bar name="bar1">
    </bar>
    <bar name="bar2">
    </bar>
    <qux>
        <foo>
            <bar name="bar3">
            </bar>
        </foo>
        <bar name="bar4">
        </bar>
    </qux>
</foo>

, вот два пути

//bar[not(parent::foo[ancestor::foo])]
//bar[1 >= count(ancestor::foo)]

, которые будут выбирать нужные элементы (протестировано в .NET).

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