2017-02-22 5 views
0

나는 XSLT를 배우고 있으며 기존 XML 파일을 필터링하려고 연습하고 기본적으로 선택된 노드 만 트리를 복사합니다. 조건이 일치하면 'test'라는 하위 문자열이 있습니다.XSL에서 필터링하는 방법?

신원 패턴을 변형하여, 나는 다음 코드가 :

<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="(node() | @*)[contains(name(.), 'test')]" /> 

<!-- Bonus Q: What would be happening behind the scenes when I put this code inside the copy element? 
<xsl:value-of select="." /> --> 

    </xsl:copy> 
</xsl:template> 

지금이 나에게 다음과 같은 출력을 얻는다, 그러나

<head> 
<testA> <testAChild /></testA> <!-- should be <testA> <testAChild> foo </testAChild></testA> --> 
<testB /> <!-- should be <testB> bar </testB> --> 
<Ctest /> <!-- should be <Ctest> foobar </Ctest> --> 
      <!-- should be <DontDeleteThis> <testD> 420 </testD></DontDeleteThis> --> 
</head> 

를,이 결과의 값을 가지고 있지 않습니다 나무. 또한 현재 노드가 거짓이지만 자식, 손주 또는 가능하면 그랜드 그랜드 자식이 기준을 통과 할 수있는 모든 경우를 검사하지 않습니다.

<head> 
    <testA> 
     <testAChild> foo </testAChild> 
    </testA> 
    <testB> bar </testB> 
    <Ctest> foobar </Ctest> 
    <DeleteThis> DELETED </DeleteThis> 
    <DontDeleteThis> 
     <testD> 420 </testD> 
    </DontDeleteThis> 
</head> 
+0

XML 파일도 제공하십시오. – AntonH

+0

@AntonH 질문을 편집하고 XML 스 니펫으로 업데이트했습니다. 나는 이런 종류의 문제에 대한 일반적인 해결책을 찾고있다. 그래서 다른 종류의 XML 구조에서도 사용할 수있을만큼 유연해야한다. – WCGPR0

답변

1

을 줄 것이다이

<xsl:template match="node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()[descendant-or-self::*[contains(name(.), 'test')]]" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="node()[contains(name(.), 'test')]"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

: 여기

은 입력 XML의 예입니다 요소 이름 W 자손 처리 명 I을 사용하려면 명시 적으로 수행해야합니다. 코드는 현재 노드의 이름 만 검사합니다. 속성 이름을 일치 시키려면 속성이 첨부 된 요소를 삭제할 수 없도록해야합니다. 예를 들면 다음과 같습니다.

<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0" xml:lang="en-latn"> 
    <output media-type="application/xml"/> 
    <template match="attribute::node() | child::node()"> 
     <copy> 
      <variable name="attributes" select="attribute::node()[contains(name(), 'test')]"/> 
      <variable name="elements" select="child::*[count((descendant-or-self::node() | attribute::node())[contains(name(), 'test')]) > 0]"/> 
      <variable name="comments" select="child::comment()[count(ancestor::node()[contains(name(), 'test')]) > 0]"/> 
      <variable name="PIs" select="child::processing-instruction()[count(ancestor-or-self::node()[contains(name(), 'test')]) > 0]"/> 
      <variable name="text" select="child::text()[count(ancestor::node()[contains(name(), 'test')]) > 0]"/> 
      <apply-templates select="$attributes | $elements | $comments | $PIs | $text"/> 
     </copy> 
    </template> 
</transform> 

루피의 코드는 처리 명령 (PI) 노드 이름과 일치하지 않습니다. *node() 사이에는 약간의 차이가 있습니다. *attributenamespace 축을 제외한 요소 노드의 줄임말이므로, node()을 사용하여 PI 노드를 일치시켜야합니다. (XPath는 2 년, element()/element(*)에서 *에 해당하는 긴 형식이있다. 나는 그 조금 덜 혼란이 개념을하게 알고 생각합니다.) 보너스 질문에 관해서는

value-of 요소는 선택된 노드에 string의 XPath 기능을 실행 . 따라서 일치 된 모든 요소에 대해 요소의 문자열 값 (즉, 연결된 모든 텍스트 노드)이 value-of 요소의 위치에 출력됩니다. 일치하는 속성, 주석, 처리 명령 및 텍스트 노드의 경우 copy 요소가 해당 노드 유형에 대한 내용을 무시하기 때문에 추가 텍스트가 출력되지 않습니다.

1

사용하면 상위 요소 이름에 일치 할 경우는, 자손에게 출력에게 당신의 욕망