2012-05-25 5 views
2

을 제외한 모든 자손 text() 노드 찾기 내 XML 문서에는 임의로 중첩 된 섹션이 있습니다. 특정 섹션에 대한 참조가 주어지면을 포함하지 않는 해당 섹션 에있는 TextNode을 모두 찾아야합니다. 경우하위 섹션

<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> 

는, 위의 분명하지 않은 : 예를 들어

아래 #a1 노드에 대한 참조 주어진, 난 단지 "A1"과 "A1"텍스트 노드를 찾을 필요 구성 데이터입니다. 특히 id 속성은 실제 문서에 존재하지 않을 수 있습니다.

지금 섹션 내의 모든 텍스트 노드를 찾은 다음 내가 원하지 않는 사람을 빼 루비를 사용하는 것입니다 위해 마련 중에 최고 :

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 

은 내가 공예 수 단일 XPath 1.0 표현식을 사용하여 이러한 노드를 직접 찾을 수 있습니까? 뭔가 같은 :

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

답변

3

사용 ("A1"의 id 속성을 가진 문자열 값으로 섹션) :

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

XSLT가 - 기반의 검증 :

0 이 변환이 제공된 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> 

UPDATE : 케이스하여 출력 및 사본 선택된 노드 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> 

이렇게하면 정확하게 s ame는 텍스트 노드를 원했습니다.

+0

'id' 속성에 의존하지 않고 이것을 할 수 있습니까? 그 점을 명확하게 설명하고 설명하기위한 데모 문서 일뿐입니다. 구분 속성이없는 중첩 된 '

'요소를 상상해보십시오. – Phrogz

+0

예,이 답변의 업데이트를 참조하십시오. –

+0

니스; 나는'count()'를 사용하는 것을 잊어 버렸지 만, 일단 그것을 사용하기 시작했다 할지라도, 당신이 어떻게 그 카운트를 "저장"하는지를 알 수 없었다. 여전히 Ruby/XPath (새 컨텍스트를 시작할 때 고유 노드가'.'이므로)에서 직접 작동하지 않지만 일반 XPath에 대한 질문에 대답하는 것으로 보입니다. – Phrogz

1

사용 :

//text()[ancestor::section[1]/@id = 'a1'] 
+0

각 섹션에 고유 한'id' 속성이있는 경우에만 작동합니다. 위의 샘플 데이터에서 그런 경우가 발생하지만 일반적인 해결책은 아닙니다. +1하지만 동의하지 않습니다. – Phrogz

+0

@Phrogz :이 경우, 질문의 텍스트에이를 지정해야합니다. 또한 특정 XPath 표현식의 필수 접두사이기 때문에 특정 '섹션'을 고유하게 선택하는 방법을 지정해야합니다. ID의 고유성에 의존하지 않는 솔루션에 대한 내 대답을 확인하십시오. –

+0

@Dimitre 어떤 섹션이라도'// section [27]'또는 (실제로는 제 경우)'doc.xpath ('// section')를 통해 유일하게 선택할 수 있습니다. ...이 특정 섹션 참조를 새로운 XPath 표현식의 앵커로 사용하십시오 ...}' – Phrogz

관련 문제