2013-12-11 3 views
0

I가 다음과 같은 XML 문서 내가 XSLT 템플릿 시도XSLT 노드 카운터

<root> 
<TotalPeople>2</TotalPeople> <!-- Needs to calculate how many "Person" tags --> 
    <MoreTagsWithData/> 
    <Person> 
     <id>1</id> <!-- incrementing per each Person --> 
     <Name>John Smith</Name> 
     <MoreTagsWithData/> 
    </Person> 
    <Person> 
     <id>2</id> 
     <Name>John Doe</Name> 
     <MoreTagsWithData/> 
    </Person> 
</root> 

문서를 얻을 필요가

<root> 
    <TotalPeople>BLABLA</TotalPeople> 
     <MoreTagsWithData/> 
     <Person> 
      <id>bla-bla</id> 
      <Name>John Smith</Name> 
      <MoreTagsWithData/> 
     </Person> 
     <Person> 
      <id>bla-bla</id> 
      <Name>John Doe</Name> 
      <MoreTagsWithData/> 
     </Person> 
    </root> 

:

<!-- copy all file (I need to save the whole file since in reality it contains much more data --> 

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

<!-- indexing ids --> 
    <xsl:template match="id"> 
    <xsl:copy> 
       <xsl:number level="any"/> 
    </xsl:copy> 
</xsl:template> 


<!-- Piece I am not sure , it does not work --> 

    <xsl:template match="TotalPeople"> 
     <xsl:copy> 
       <xsl:number level="any" count="/root/Person/id"/> 
     </xsl:copy> 
    </xsl:template> 

내가 필요를 문서에서 얼마나 많은 태그를 계산하고이 값으로 내 문서의 특수 태그를 수정하십시오. 실제 문서에는 유지 관리해야 할 많은 정보가 포함되어 있으므로 새 문서를 만들 수 없습니다.

<xsl:template match="TotalPeople"> 
    <xsl:copy> 
     <xsl:value-of select="count(/root/Person/id)"/> 
     <!-- or just select="count(/root/Person)" --> 
    </xsl:copy> 
</xsl:template> 

XSLT 스타일 시트는 현재 위치에서 문서를 편집 할 수 없습니다, 별도의 출력 문서에 입력 XML 문서를 변환하도록 설계되어 다음과 같이

답변

0

당신은 마지막 템플릿을 변경할 수 있습니다. 위의 내용은 요청한 출력 문서를 생성하지만 기존 문서는 수정하지 않습니다. 적어도, 나는 그렇게 할 XSLT 프로세서를 모른다. 대신 입력 XML 파일을 삭제하고 출력 XML의 이름을 바꾸어 대체 할 수 있습니다.

1

아래와 같은 스타일 시트를 사용하고 입력 XML 문서를 @LarsH와 같은 별도의 출력 문서로 변환 할 수 있습니다. 당신은 XSLT 2.0을 사용할 수 있는지

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="TotalPeople"> 
     <xsl:copy> 
      <xsl:value-of select="count(../Person)"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="id"> 
     <xsl:copy> 
      <xsl:number count="Person"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

그러나, 당신은 당신의 원본 파일을 덮어 collection(), xsl:result-documentdocument-uri()를 사용하여 시도 할 수 있습니다. 그것은 일종의 해키이며 여전히 입력 XML을 삭제하고 출력 XML의 이름을 바꾸는 것이 좋습니다.

XSLT 2.0 나는 당신이 할 수있는 실현하지 않았다 ...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:param name="dir" select="'C:/Path/To/Doc'"/> 
    <xsl:param name="file" select="'input.xml'"/> 

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

    <xsl:template match="/"> 
     <xsl:for-each select="collection(concat('file:///',$dir,'?select=',$file))"> 
      <xsl:result-document href="{document-uri(current())}"> 
       <xsl:apply-templates/> 
      </xsl:result-document> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="TotalPeople"> 
     <xsl:copy> 
      <xsl:value-of select="count(../Person)"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="id"> 
     <xsl:copy> 
      <xsl:number count="Person"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

흥미 롭 (나는 단지 색슨-HE 9.4. 이것을 테스트). 입력 된 문서를 덮어 쓰면 원본을 읽을 때까지 덮어 쓰기를 시작할 수 있습니까? – LarsH

+1

@LarsH - 확실하지 않습니다. 스트리밍 중이 아니기 때문에 처리/덮어 쓰기가 시작되기 전에 전체 입력을 읽고 메모리에 저장해야한다고 생각합니다. 난이 두 번 해본 적이 있고 두 번 스택 오버플로 답변했다. 테스트 할 때 어떤 문제도 발생하지 않았지만 데이터 세트는 작았습니다. –