当前文档中的XSLT节点计数器

时间:2013-12-11 19:49:04

标签: xml xslt numbers counter

我有以下xml文档

<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>

我需要获取文件

 <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>

我尝试过XSLT模板:

<!-- 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>

我需要计算文档中的标签数量,并使用此值修改文档中的特殊标记。我无法创建新文档,因为真实文档包含了我需要维护的大量信息。

2 个答案:

答案 0 :(得分:1)

您可以使用下面的样式表之类的内容,并将输入的XML文档转换为单独的输出文档,如@LarsH所说。

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>

但是,如果您可以使用XSLT 2.0,则可以尝试使用collection()xsl:result-documentdocument-uri()覆盖原始文件。这有点hacky,我仍然建议删除输入XML并重命名输出XML。

XSLT 2.0 (我只用Saxon-HE 9.4进行了测试。)

<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>

答案 1 :(得分:0)

您可以按如下方式更改最后一个模板:

<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文档转换为单独的输出文档,而不是就地编辑文档。以上将生成您请求的输出文档,但不会修改您现有的文档。至少,我不知道XSLT处理器会做到这一点。相反,您可以删除输入XML文件并重命名输出XML以替换它。