Xpath: отфильтровывать дочерние элементы - PullRequest
5 голосов
/ 03 марта 2011

Я ищу выражение xpath, которое отфильтровывает определенных потомков. Ребенок должен содержать узел CCC с буквой B.

Источник:

<AAA>
    <BBB1>
        <CCC>A</CCC>
    </BBB1>       
    <BBB2>
        <CCC>A</CCC>
    </BBB2>
    <BBB3>
        <CCC>B</CCC>
    </BBB3>
    <BBB4>
        <CCC>B</CCC>
    </BBB4>
</AAA>

Это должен быть результат:


<AAA>
    <BBB3>
        <CCC>B</CCC>
    </BBB3>
    <BBB4>
        <CCC>B</CCC>
    </BBB4>
</AAA>

Надеюсь, кто-нибудь сможет мне помочь.

Jos

Ответы [ 4 ]

4 голосов
/ 05 марта 2011

XPath - это язык запросов для документов XML. Таким образом, он может только выбирать узлы из существующих документов XML - он не может изменять документ XML или создавать новый документ XML .

Используйте XSLT для преобразования XML-документа и создания из него нового XML-документа.

В данном конкретном случае :

<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>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/*/*[not(CCC = 'B')]"/>
</xsl:stylesheet>

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

<AAA>
    <BBB1>
        <CCC>A</CCC>
    </BBB1>
    <BBB2>
        <CCC>A</CCC>
    </BBB2>
    <BBB3>
        <CCC>B</CCC>
    </BBB3>
    <BBB4>
        <CCC>B</CCC>
    </BBB4>
</AAA>

желаемый, правильный результат:

<AAA>
   <BBB3>
      <CCC>B</CCC>
   </BBB3>
   <BBB4>
      <CCC>B</CCC>
   </BBB4>
</AAA>
1 голос
/ 03 марта 2011

Чтобы выбрать все нужные элементы и текстовые узлы, используйте этот XPATH:

//node()[.//CCC[.='B']
      or self::CCC[.='B']
      or self::text()[parent::CCC[.='B']]]

Этого можно добиться с помощью более простого / легкого использования XPATH с измененным преобразованием идентичности XSLT:

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

    <!--Empty template for the content we want to redact -->
    <xsl:template match="*[CCC[not(.='B')]]" />

    <!--By default, copy all content forward -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
0 голосов
/ 03 марта 2011

Если вы хотите получить AAA, BBB3 и BBB4, вы можете использовать следующее

//*[descendant::CCC[text()='B']]

Если только BBB3 и BBB4, то

//*[CCC[text()='B']]
0 голосов
/ 03 марта 2011

попробуйте это,

         "//CCC[text() = 'B']"

Он должен дать все узлы CCC, где внутренний текст равен B.

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