2

私のXMLドキュメントには任意にネストされたセクションがあります。特定のセクションへの参照を考えると、サブセクションを含まないTextNodeそのセクションのすべてのを見つける必要があります。

たとえば、#a1以下のノードへの参照を考えると、「A1」と「A1」のテキストノードのみを見つける必要があります。

<root>
  <section id="a1">
    <b>A1 <c>A1</c></b>
    <b>A1 <c>A1</c></b>
    <section id="a1.1">
      <b>A1.1 <c>A1.1</c></b>
    </section>
    <section id="a1.2">
      <b>A1.2 <c>A1.2</c></b>
      <section id="a1.2.1">
        <b>A1.2.1</b>
      </section>
      <b>A1.2 <c>A1.2</c></b>
    </section>
  </section>
  <section id="a2">
    <b>A2 <c>A2</c></b>
  </section>
</root>

不明な点がある場合は、上記のデータを作成します。特にid属性は、実際のドキュメントには存在しない場合があります。

今のところ私が思いついた最善の方法は、セクション内のすべてのテキストノードを見つけてから、Rubyを使用して不要なノードを差し引くことです。

def own_text(node)
  node.xpath('.//text()') - node.xpath('.//section//text()')
end

doc = Nokogiri.XML(mydoc,&:noblanks)
p own_text(doc.at("#a1")).length #=> 4

これらのノードを直接見つけるために単一のXPath1.0式を作成できますか?何かのようなもの:

.//text()[ancestor::section = self] # self being the original context node
4

2 に答える 2

3

使用id(文字列値が「a1」の属性を持つセクションの場合):

   //section[@id='a1']
       //*[normalize-space(text()) and ancestor::section[1]/@id = 'a1']/text()

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="/">
     <xsl:copy-of select=
      "//section[@id='a1']
           //*[normalize-space(text()) and ancestor::section[1]/@id = 'a1']
     "/>
 </xsl:template>
</xsl:stylesheet>

この変換が提供されたXMLドキュメントに適用される場合:

<root>
    <section id="a1">
        <b>A1 
            <c>A1</c>
        </b>
        <b>A1 
            <c>A1</c>
        </b>
        <section id="a1.1">
            <b>A1.1 
                <c>A1.1</c>
            </b>
        </section>
        <section id="a1.2">
            <b>A1.2 
                <c>A1.2</c>
            </b>
            <section id="a1.2.1">
                <b>A1.2.1</b>
            </section>
            <b>A1.2 
                <c>A1.2</c>
            </b>
        </section>
    </section>
    <section id="a2">
        <b>A2 
            <c>A2</c>
        </b>
    </section>
</root>

XPath式を評価し(必要なテキストノードの親のみを選択して、結果を明確に表示するため)、選択したノードを出力にコピーします

<b>A1 
            <c>A1</c>
</b>
<c>A1</c>
<b>A1 
            <c>A1</c>
</b>
<c>A1</c>

更新section要素が同じid属性を持つことができる(またはid属性がまったくない)場合は、次を使用します。

       (//section)[1]
           //*[normalize-space(text())
           and
              count(ancestor::section)
             =
               count((//section)[1]/ancestor::section) +1]/text()

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="/">
         <xsl:copy-of select=
          "(//section)[1]
               //*[normalize-space(text())
               and
                  count(ancestor::section)
                 =
                   count((//section)[1]/ancestor::section) +1]
         "/>
     </xsl:template>
</xsl:stylesheet>

変換結果(同じ)

<b>A1 
            <c>A1</c>
</b>
<c>A1</c>
<b>A1 
            <c>A1</c>
</b>
<c>A1</c>

これにより、まったく同じ必要なテキストノードが選択されます。

于 2012-05-26T02:20:37.403 に答える
1

使用する:

//text()[ancestor::section[1]/@id = 'a1']
于 2012-05-25T23:41:57.603 に答える