2012-08-24 2 views
1

여기이 질문에 대한 몇 가지 변형을 보았습니다.하지만 상황에 적용하는 방법을 모르겠습니다. 그래서 누군가가 나를 도와 줄 수 있기를 바랍니다.속성을 키로 사용하여 XSLT 구조 심화하기

<item id="1"/> 
<item id="1.1"/> 
<item id="1.1.1"/> 
<item id="1.1.2"/> 
<item id="1.1.2.1"/> 
<item id="1.2"/> 
<item id="1.3"/> 

나는, id 속성에 따라 계층 적으로 태그를 설정과 같이 찾고 있어요 :

<item id="1"> 
    <item id="1.1"> 
    <item id="1.1.1"/> 
    <item id="1.1.2"> 
     <item id="1.1.2.1"/> 
    </item> 
    </item> 
    <item id="1.2"/> 
    <item id="1.3"/> 
</item> 

나는 이것과 같은 형식으로 플랫 XML 파일이

일부 id 값에는 두 개의 숫자가 있습니다 (예 : "1.2.3.15.1").

도움 말?

+0

당신의 종료 조건. 당신이해야 할 일은 1,1.1,1.2,1.3 .. 1.nnn과 같은 값으로 재귀 적으로 호출하는 함수를 가지며, 각각에 대해 1.1.1, 1.1.2 등을 다시 호출하는 것입니다. 각 시리즈 미리 정의 된 조건에서 끝내야합니다. –

+0

최적화는 모든 속성을 먼저 수집하고 필요한 순서대로 정렬하여 해당 속성 만 호출하여 종료가 하드 코딩되지 않도록 할 수 있습니다. –

답변

3

올바른 노드를 선택하는 것은 어려울 수 있지만, 당신이 (당신이 그것에 루트 요소를 추가하는 경우)이 샘플 입력 작업에는 계층 구조가 없기 때문에 여기에

<!-- start somewhere --> 
    <xsl:template match="/root"> 
    <root> 
     <!-- select all with no . in the id --> 
     <xsl:apply-templates select="//item[string-length(translate(@id,'1234567890',''))=0]" /> 
    </root> 
    </xsl:template> 

    <xsl:template match="item"> 
    <xsl:variable name="id" select="@id"/> 
    <!-- how many . have we ? That is how deep we are and add 1 --> 
    <xsl:variable name="deep" select="string-length(translate(@id,'1234567890',''))+1" /> 
    <xsl:copy> 
     <!-- copy attribs over --> 
     <xsl:apply-templates select="@*"/> 
     <!-- select all nodes that start with our curent id, 
      select nodes that are just one level below us 
      and don't select our selfs--> 
     <xsl:apply-templates select="//item[starts-with(@id, $id) and string-length(translate(@id,'1234567890',''))=$deep and not(@id=$id)]"/> 
    </xsl:copy> 
    </xsl:template> 

    <!-- copy attribs --> 
    <xsl:template match="@*"> 
    <xsl:copy /> 
    </xsl:template> 
+0

감사. 이 하나는 속임수를 썼지 만 한 가지 수정해야했던 부분이있었습니다. 입력 파일의 ID가 두 자리 숫자 (예 : 1.2.3.11)로되어있어 노드 선택에 실패했습니다. 첫 번째 패스 변환으로 ID를 두 자리 숫자 (예 : 01.02.03.11)로 형식을 지정하여 해결했습니다. – NestorDRod

1

I. 간단한 XSLT 2.0 솔루션입니다 수 있습니다 (및 유사한 XSLT 1.0 용액이 한 후에 다음)

이 변환이 XML 문서 (제공된 XML 프래그먼트, 래핑 위트인가
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/*"> 
    <xsl:sequence select="my:grouping(*, 1)"/> 
</xsl:template> 

<xsl:function name="my:grouping" as="element()*"> 
    <xsl:param name="pNodes" as="element()*"/> 
    <xsl:param name="pLevel" as="xs:integer"/> 

    <xsl:if test="$pNodes"> 
     <xsl:for-each-group select="$pNodes" group-by="tokenize(@id, '\.')[$pLevel]"> 
     <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:sequence select=" 
      my:grouping(current-group()[tokenize(@id, '\.')[$pLevel+1]], $pLevel+1)"/> 
     </xsl:copy> 
    </xsl:for-each-group> 
    </xsl:if> 
</xsl:function> 
</xsl:stylesheet> 

힌 하나의 상위 요소가 잘 구성된 XML 문서) 만드는 :

<t> 
    <item id="1"/> 
    <item id="1.1"/> 
    <item id="1.1.1"/> 
    <item id="1.1.2"/> 
    <item id="1.1.2.1"/> 
    <item id="1.2"/> 
    <item id="1.3"/> 
</t> 

원하는 정확한 결과는을 생성됩니다

<item id="1"> 
    <item id="1.1"> 
     <item id="1.1.1"/> 
     <item id="1.1.2"> 
     <item id="1.1.2.1"/> 
     </item> 
    </item> 
    <item id="1.2"/> 
    <item id="1.3"/> 
</item> 

II.

<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="kFollowing" match="item" 
    use="generate-id(preceding-sibling::* 
        [string-length(current()/@id) > string-length(@id) 
        and 
         starts-with(current()/@id, concat(@id, '.'))] 
         [1])"/> 

<xsl:template match="/*"> 
    <xsl:call-template name="grouping"> 
     <xsl:with-param name="pNodes" select="*"/> 
     <xsl:with-param name="pLevel" select="1"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="grouping"> 
    <xsl:param name="pNodes"/> 
    <xsl:param name="pLevel" select="1"/> 

    <xsl:for-each select= 
    "$pNodes[$pLevel > string-length(@id) - string-length(translate(@id, '.', ''))]"> 
    <xsl:copy> 
    <xsl:copy-of select="@*"/> 

    <xsl:call-template name="grouping"> 
     <xsl:with-param name="pNodes" select="key('kFollowing', generate-id())"/> 
     <xsl:with-param name="pLevel" select="$pLevel+1"/> 
    </xsl:call-template> 
    </xsl:copy> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

이 XSLT 1.0 변환이 같은 문서 (위), 같은 원하는 정확한 결과가을 생산에 적용됩니다 : 여기에 비슷한 XSLT 1.0 솔루션입니다

은 무엇입니까
<item id="1"> 
    <item id="1.1"> 
     <item id="1.1.1"/> 
     <item id="1.1.2"> 
     <item id="1.1.2.1"/> 
     </item> 
    </item> 
    <item id="1.2"/> 
    <item id="1.3"/> 
</item>