Счетчик проверок XPath 1.0

У меня есть следующий XML-документ:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE inventory SYSTEM "books.dtd">
<inventory>
    <book num="b1">
        <title>Snow Crash</title>
        <author>Neal Stephenson</author>
        <publisher>Spectra</publisher>
        <price>14.95</price>
        <chapter>
            <title>Snow Crash - Chapter A</title>
            <paragraph>
                This is the <emph>first</emph> paragraph.
                <image file="firstParagraphImage.gif"/>
                afetr image...
            </paragraph>
            <paragraph>
                This is the <emph>second</emph> paragraph.
                <image file="secondParagraphImage.gif"/>
                afetr image...
            </paragraph>
        </chapter>
        <chapter>
            <title>Snow Crash - Chapter B</title>
            <section>
                <title>Chapter B - section 1</title>
                <paragraph>
                    This is the <emph>first</emph> paragraph of section 1 in chapter B.
                    <image file="Chapter_B_firstParagraphImage.gif"/>
                    afetr image...
                </paragraph>
                <paragraph>
                    This is the <emph>second</emph> paragraph of section 1 in chapter B.
                    <image file="Chapter_B_secondParagraphImage.gif"/>
                    afetr image...
                </paragraph>
            </section>
        </chapter>
        <chapter>
            <title>Chapter C</title>
            <paragraph>
                This chapter has no images and only one paragraph
            </paragraph>
        </chapter>
    </book>
    <book num="b2">
        <title>Burning Tower</title>
        <author>Larry Niven</author>
        <author>Jerry Pournelle</author>
        <publisher>Pocket</publisher>
        <price>5.99</price>
        <chapter>
            <title>Burning Tower - Chapter A</title>
        </chapter>
        <chapter>
            <title>Burning Tower - Chapter B</title>
            <paragraph>
                This is the <emph>second</emph> paragraph of chapter B in the 2nd book.
                <image file="Burning_Tower_Chapter_B_secondParagraphImage.gif"/>
                afetr image...
            </paragraph>
        </chapter>
    </book>
    <book num="b3">
        <title>Zodiac</title>
        <author>Neal Stephenson</author>
        <publisher>Spectra</publisher>
        <price>7.50</price>
        <chapter>
            <title>Zodiac - Chapter A</title>
        </chapter>
    </book>
    <!-- more books... -->
</inventory>

Как написать выражение XPath 1.0 для выбора всех книг, содержащих более 1 изображения?

Я попробовал inventory/book//image[2]/ancestor::book, но это дало неверный результат...

inventory/book//image[2] дает все 2-е изображения в каждой книге?


person URL87    schedule 23.05.2012    source источник


Ответы (3)


Использование:

/*/book[(.//image)[2]]

При этом выбираются все элементы book, которые являются дочерними элементами верхнего элемента XML-документа и имеют второго потомка image.

Это выражение оценивается потенциально быстрее, чем любое выражение, начинающееся с //, поскольку выражение, начинающееся с //, обычно приводит к обходу всего документа.

Это также более эффективно, чем:

//book[count(.//image)>1] 

даже если это выражение было переписано так, чтобы оно не начиналось с //.

Это так, потому что в приведенном выше выражении count(.//image) приводит к подсчету всех потомков image, а в нашем решении:

(.//image)[2]

только проверяет, что второй потомок image существует.

И наконец, проверка на основе XSLT:

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

 <xsl:template match="node()|@*">
     <xsl:copy-of select="/*/book[(.//image)[2]]"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному XML-документу:

<inventory>
        <book num="b1">
            <title>Snow Crash</title>
            <author>Neal Stephenson</author>
            <publisher>Spectra</publisher>
            <price>14.95</price>
            <chapter>
                <title>Snow Crash - Chapter A</title>
                <paragraph>
                    This is the <emph>first</emph> paragraph.
                    <image file="firstParagraphImage.gif"/>
                    afetr image...
                </paragraph>
                <paragraph>
                    This is the <emph>second</emph> paragraph.
                    <image file="secondParagraphImage.gif"/>
                    afetr image...
                </paragraph>
            </chapter>
            <chapter>
                <title>Snow Crash - Chapter B</title>
                <section>
                    <title>Chapter B - section 1</title>
                    <paragraph>
                        This is the <emph>first</emph> paragraph of section 1 in chapter B.
                        <image file="Chapter_B_firstParagraphImage.gif"/>
                        afetr image...
                    </paragraph>
                    <paragraph>
                        This is the <emph>second</emph> paragraph of section 1 in chapter B.
                        <image file="Chapter_B_secondParagraphImage.gif"/>
                        afetr image...
                    </paragraph>
                </section>
            </chapter>
            <chapter>
                <title>Chapter C</title>
                <paragraph>
                    This chapter has no images and only one paragraph
                </paragraph>
            </chapter>
        </book>
        <book num="b2">
            <title>Burning Tower</title>
            <author>Larry Niven</author>
            <author>Jerry Pournelle</author>
            <publisher>Pocket</publisher>
            <price>5.99</price>
            <chapter>
                <title>Burning Tower - Chapter A</title>
            </chapter>
            <chapter>
                <title>Burning Tower - Chapter B</title>
                <paragraph>
                    This is the <emph>second</emph> paragraph of chapter B in the 2nd book.
                    <image file="Burning_Tower_Chapter_B_secondParagraphImage.gif"/>
                    afetr image...
                </paragraph>
            </chapter>
        </book>
        <book num="b3">
            <title>Zodiac</title>
            <author>Neal Stephenson</author>
            <publisher>Spectra</publisher>
            <price>7.50</price>
            <chapter>
                <title>Zodiac - Chapter A</title>
            </chapter>
        </book>
        <!-- more books... -->
</inventory>

Вычисляется выражение XPath, и выбранные узлы (в данном случае только один) копируются в выходные данные:

<book num="b1">
   <title>Snow Crash</title>
   <author>Neal Stephenson</author>
   <publisher>Spectra</publisher>
   <price>14.95</price>
   <chapter>
      <title>Snow Crash - Chapter A</title>
      <paragraph>
                    This is the <emph>first</emph> paragraph.
                    <image file="firstParagraphImage.gif"/>
                    afetr image...
                </paragraph>
      <paragraph>
                    This is the <emph>second</emph> paragraph.
                    <image file="secondParagraphImage.gif"/>
                    afetr image...
                </paragraph>
   </chapter>
   <chapter>
      <title>Snow Crash - Chapter B</title>
      <section>
         <title>Chapter B - section 1</title>
         <paragraph>
                        This is the <emph>first</emph> paragraph of section 1 in chapter B.
                        <image file="Chapter_B_firstParagraphImage.gif"/>
                        afetr image...
                    </paragraph>
         <paragraph>
                        This is the <emph>second</emph> paragraph of section 1 in chapter B.
                        <image file="Chapter_B_secondParagraphImage.gif"/>
                        afetr image...
                    </paragraph>
      </section>
   </chapter>
   <chapter>
      <title>Chapter C</title>
      <paragraph>
                    This chapter has no images and only one paragraph
                </paragraph>
   </chapter>
</book>
person Dimitre Novatchev    schedule 23.05.2012

попробуй с этим

//book[count(.//image)>1]

все книги, которые где-то имеют более одного тега изображения

person neu-rah    schedule 23.05.2012

inventory/book//image[2]/ дает вам второе изображение, если в вашем элементе book есть 2 или более дочерних узла image. Пытаться:

   //inventory/book[count(descendant::image) > 1]

Вам нужно перейти вниз по иерархии к элементу book, а затем начать свой запрос оттуда. Предикат (или запрос с точки зрения непрофессионала) заключается в поиске всех элементов image оттуда и далее — именно это и делает ось descendant. Вы добавляете :: и nodename для выбора конкретного потомка, как мы делаем с descendant::image для поиска всех image. Последний тест, чтобы убедиться, что count (как следует из названия функции) больше 1 или нет.

person dirkgently    schedule 23.05.2012