2012-04-04 2 views
3

요소의 하위 요소에 대한 특성 값 목록을 검색하려고 시도하지만 값이 한 번만 표시되기를 원합니다.XSLT에서 각 요소와 관련된 불일치를 선택하십시오.

는 예를 들어, 나는 다음과 같은 XML

<root> 
    <sec> 
     <nom-title> 
      <nom-chapter> 
       <nom-article><data att="1.1"/></nom-article> 
       <nom-article> 
        <nom-item><data att="1.1"/></nom-item> 
        <nom-item><data att="1.2"/></nom-item> 
       </nom-article> 
      </nom-chapter> 
      <nom-chapter> 
       <nom-article><data att="2.1"/></nom-article> 
       <nom-article><data att="1.1"/></nom-article> 
      </nom-chapter> 
     </nom-title> 
     <nom-title> 
      <nom-chapter> 
       <nom-article><data att="1.1"/></nom-article> 
      </nom-chapter> 
     </nom-title> 
    </sec> 
</root> 

이 그리고 그런 결과 원하는 :

<root> 
    <nom-title> 
     <att>1.1</att> 
     <att>1.2</att> 
     <att>2.1</att> 
     <nom-chapter> 
      <att>1.1</att> 
      <att>1.2</att> 
      <nom-article> 
       <att>1.1</att> 
      </nom-article> 
      <nom-article> 
       <att>1.1</att> 
       <att>1.2</att> 
       <nom-item><att>1.1</att></nom-item> 
       <nom-item><att>1.2</att></nom-item> 
      </nom-article> 
     </nom-chapter> 
    </nom-title> 
    <nom-title> 
     <att>1.1</att> 
     <nom-chapter> 
      <att>1.1</att> 
      <nom-article> 
       <att>1.1</att> 
      </nom-article> 
     </nom-chapter> 
    </nom-title> 
</root> 

나는 XSL 사용하려고했습니다 핵심 요소를하지만, 그것은 단지 반환 하나의 요소에 대한 값. 이 예제에서는 첫 번째 제목은 1.1을 반환하지만 두 번째 제목은 1.1을 반환하지 않습니다. 내가 사용했던 XSL :

<xsl:key name="allAtt" 
    match="//*[starts-with(name(.),'nom-')]/data" 
    use="@att"/> 
<xsl:template match="nom-title|nom-chapter|nom-article|nom-item"> 
    <xsl:element name="name(.)"> 
     <xsl:apply-templates select=".//*[starts-with(name(.),'nom-')]/data 
    </xsl:element> 
</xsl:template>   
<xsl:template match="data"> 
     <xsl:variable name="att" select="@att"/> 
     <xsl:if test="generate-id(.)=generate-id(key('allAtt',$att)[1]"> 
      <xsl:element name="att"><xsl:value-of select="$att"></xsl:element> 
     </xsl:if> 
</xsl:template> 
+2

xslt에 대한 경험으로는 유효한 XML이 있어야합니다. "nom-article"요소가 닫히지 않은 것 같습니다. 먼저 해결하려고 할 수 있습니다. –

+1

Justin에 동의합니다. 올바른 형식의 XML 입력 샘플을 먼저 보여주십시오. 현재 입력 구조가 명확하지 않고 여러 태그가 제대로 닫히지 않았습니다 (예 :'', ' ). –

+0

죄송합니다. 복사 붙여 넣기가 잘못되었습니다. 수정했습니다. – claudex

답변

2

이 변환 :

<root> 
    <sec> 
     <nom-title> 
      <nom-chapter> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
       <nom-article> 
        <nom-item> 
         <data att="1.1"/> 
        </nom-item> 
        <nom-item> 
         <data att="1.2"/> 
        </nom-item> 
       </nom-article> 
      </nom-chapter> 
      <nom-chapter> 
       <nom-article> 
        <data att="2.1"/> 
       </nom-article> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
      </nom-chapter> 
     </nom-title> 
     <nom-title> 
      <nom-chapter> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
      </nom-chapter> 
     </nom-title> 
    </sec> 
</root> 

이 원하는 정확한 결과를 생성 : 제공된 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:key name="kData-nom-article" match="data" use= 
"concat(generate-id(ancestor::nom-article[1]), 
     '+', @att)"/> 
<xsl:key name="kData-nom-chapter" match="data" use= 
"concat(generate-id(ancestor::nom-chapter[1]), 
     '+', @att)"/> 
<xsl:key name="kData-nom-title" match="data" use= 
"concat(generate-id(ancestor::nom-title[1]), 
     '+', @att)"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="sec"><xsl:apply-templates/></xsl:template> 

<xsl:template match="nom-title|nom-article|nom-chapter"> 
    <xsl:copy> 
    <xsl:apply-templates mode="list" select= 
    ".//data[generate-id() 
      = 
       generate-id(key(concat('kData-', name(current())), 
           concat(generate-id(current()), 
            '+', @att 
            ) 
          ) 
           [1] 
         ) 
      ]"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="data" mode="list"> 
    <att><xsl:value-of select="@att"/></att> 
</xsl:template> 

<xsl:template match="non-item/data"> 
    <att><xsl:value-of select="@att"/></att> 
</xsl:template> 

<xsl:template match="*[not(self::nom-item)]/data"/> 
</xsl:stylesheet> 

:

<root> 
    <nom-title> 
     <att>1.1</att> 
     <att>1.2</att> 
     <att>2.1</att> 
     <nom-chapter> 
     <att>1.1</att> 
     <att>1.2</att> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     <nom-article> 
      <att>1.1</att> 
      <att>1.2</att> 
      <nom-item> 
       <data att="1.1"/> 
      </nom-item> 
      <nom-item> 
       <data att="1.2"/> 
      </nom-item> 
     </nom-article> 
     </nom-chapter> 
     <nom-chapter> 
     <att>2.1</att> 
     <att>1.1</att> 
     <nom-article> 
      <att>2.1</att> 
     </nom-article> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     </nom-chapter> 
    </nom-title> 
    <nom-title> 
     <att>1.1</att> 
     <nom-chapter> 
     <att>1.1</att> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     </nom-chapter> 
    </nom-title> 
</root> 

설명 : 동적으로 실제 그룹에 대한 키의 이름을 구성하여, 하나로 세 가지 Muenchian 그룹을 표현 수행 할 수 있습니다.

기억 키 이름이 문자열 필요한 경우 (이러한 경우와 같이)이고, 이름은 동적으로 생성 또는 파라미터로서 전달 될 수있다.

관련 문제