Xml 当前文档中的XSLT节点计数器
我有以下xml文档Xml 当前文档中的XSLT节点计数器,xml,xslt,numbers,counter,Xml,Xslt,Numbers,Counter,我有以下xml文档 <root> <TotalPeople>BLABLA</TotalPeople> <MoreTagsWithData/> <Person> <id>bla-bla</id> <Name>John Smith</Name> <MoreTagsWithData/&g
<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>
2.
1.
约翰·史密斯
2.
无名氏
我尝试了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>
我需要计算文档中有多少个标记,并使用此值修改文档中的特殊标记。我无法创建新文档,因为真实文档包含大量信息,我需要对其进行维护 您可以按如下方式更改最后一个模板:
<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以替换它。您可以使用下面的样式表之类的东西,将输入XML文档转换为单独的输出文档,如@LarsH said XSLT1.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>
有趣的。。。我没想到你能做到。如果您覆盖输入文档,是否保证在它阅读完原始文档之前不会开始覆盖?@LarsH-我不确定。由于它不是流式传输,我认为在开始处理/覆盖之前,必须读取整个输入并将其存储在内存中。我只做了两次,这两次都是针对堆栈溢出的答案。我在测试时没有遇到任何问题,但数据集很小。
<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>