2012-09-25 4 views
5

입력 XML 변환XSLT 병합/단일 노드에 같은 이름의 형제 노드의 값을 연결

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/catalog"> 
     <products> 
      <xsl:for-each select="product"> 
       <product> 
        <id><xsl:value-of select="@id"/></id> 
        <name><xsl:value-of select="name"/></name> 
        <category><xsl:value-of select="category" /></category> 
       </product> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 
</xsl:stylesheet> 

실제 출력의 XML

<catalog> 
    <product id="1"> 
     <name>abc</name> 
     <category>aaa</category> 
     <category>bbb</category> 
     <category>ccc</category> 
    </product> 
    <product id="2"> 
     <name>cde</name> 
     <category>aaa</category> 
     <category>bbb</category> 
    </product> 
</catalog> 

예상 XML 출력

<products> 
    <product> 
     <id>1</id> 
     <name>abc</name> 
     <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
     <id>2</id> 
     <name>cde</name> 
     <category>aaa,bbb</category> 
    </product> 
</products> 

XSLT : (

<products> 
    <product> 
     <id>1</id> 
     <name>abc</name> 
     <category>aaa</category> 
    </product> 
    <product> 
     <id>2</id> 
     <name>cde</name> 
     <category>aaa</category> 
    </product> 
</products> 

'제품'아래에 '형'이라는 이름으로 모든 형제 노드를 반복하고 단일 노드로 병합/쉼표로 구분 된 연결에 코드가 필요합니다. '카테고리'의 수는 모든 제품마다 다르므로 그 수를 알 수 없습니다.

답변

8

here 정의이 편리 가입 전화 템플릿을 사용하여,이처럼 간단하게 :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/catalog"> 
     <products> 
      <xsl:for-each select="product"> 
       <product> 
        <id> 
         <xsl:value-of select="@id"/> 
        </id> 
        <name> 
         <xsl:value-of select="name"/> 
        </name> 
        <category> 
         <xsl:call-template name="join"> 
          <xsl:with-param name="list" select="category" /> 
          <xsl:with-param name="separator" select="','" /> 
         </xsl:call-template> 
        </category> 
       </product> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 

    <xsl:template name="join"> 
     <xsl:param name="list" /> 
     <xsl:param name="separator"/> 

     <xsl:for-each select="$list"> 
      <xsl:value-of select="." /> 
      <xsl:if test="position() != last()"> 
       <xsl:value-of select="$separator" /> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

출력 :

만 코드에 작은 변화를 만들 필요가 XSLT 2.0
<products> 
    <product> 
    <id>1</id> 
    <name>abc</name> 
    <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
    <id>2</id> 
    <name>cde</name> 
    <category>aaa,bbb</category> 
    </product> 
</products> 
6

:

<category><xsl:value-of select="category" separator=","/></category> 

XSLT 1.0 솔루션이 필요한 경우 그렇게 말하는 것이 좋습니다. 일부 환경의 일부 사용자는 1.0에 고정되어 있지만 많은 사용자는 그렇지 않습니다.

+0

아, 1.0 및 xslt 스타일 시트 버전에서 그렇게 말합니다. – user1677271

+1

스타일 시트의 버전 번호는 사용중인 XSLT 프로세서의 기능 또는 프로젝트를 최신 프로세서로 옮길 수있는 기능에 대해 알려주지 않습니다. –

3

다른 XSLT 1.0 솔루션이 있습니다.

<catalog> 
    <product id="1"> 
    <name>abc</name> 
    <category>aaa</category> 
    <category>bbb</category> 
    <category>ccc</category> 
    </product> 
    <product id="2"> 
    <name>cde</name> 
    <category>aaa</category> 
    <category>bbb</category> 
    </product> 
</catalog> 

... 원하는 결과가 생성됩니다 :

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
version="1.0"> 
    <xsl:output omit-xml-declaration="no" indent="yes" /> 
    <xsl:strip-space elements="*" /> 

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

    <xsl:template match="product"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[not(self::category)]" /> 
     <category> 
     <xsl:apply-templates select="category/text()" /> 
     </category> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="category/text()"> 
    <xsl:if test="position() &gt; 1">,</xsl:if> 
    <xsl:value-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

... 영업의 원래 XML에 적용이 XSLT가

<?xml version="1.0"?> 
<catalog> 
    <product> 
    <name>abc</name> 
    <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
    <name>cde</name> 
    <category>aaa,bbb</category> 
    </product> 
</catalog> 

설명 :

  • 첫 번째 템플릿 - Identity Template은 - -이 같은 결과 문서에 모든 노드와 속성 복사를 일치합니다.
  • 두 번째 템플릿은 새로운 <category> 요소를 만들고 문서의 현재 위치에서 각 <category> 요소의 텍스트 하위를 처리하여 ID 템플릿을 재정의합니다.
  • 최종 템플릿은 필요에 따라 텍스트 값과 쉼표를 출력합니다.
+0

시도해 보지 않았지만 다른 솔루션을 이해해 주셔서 감사합니다. :) – user1677271