我有以下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>
我需要计算文档中的标签数量,并使用此值修改文档中的特殊标记。我无法创建新文档,因为真实文档包含了我需要维护的大量信息。
答案 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-document
和document-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以替换它。