我有一个XML文档,我想为其生成唯一的ID。某些节点可能已经具有该属性,在这种情况下要替换它。我希望文档中的所有节点都具有该属性。
示例文档将是
<root>
<anode uid='123'/>
<anode/>
</root>
我使用以下样式表
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="uid">
<xsl:value-of select="generate-id(.)"/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我得到以下输出。这接近我想要的,但是如何防止将现有ID创建为文本节点?
<root uid="id515559">
<anode uid="id515560">123</anode>
<anode uid="id515562"/>
</root>
我查看了XSLT: How to change an attribute value during <xsl:copy>?,但我无法创建新属性。
如果它有所不同,我正在使用lxml来处理样式表。
答案 0 :(得分:1)
您需要做的就是添加模板以匹配现有的 uid 属性,并忽略它......
<xsl:template match="@uid" />
所以,使用这个样式表......
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="uid">
<xsl:value-of select="generate-id(.)"/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@uid" />
</xsl:stylesheet>
当应用于您的示例XML时,输出如下:
<root uid="IDAEQLT">
<anode uid="IDA3XLT"></anode>
<anode uid="IDA0XLT"></anode>
</root>
答案 1 :(得分:0)
Built-in template rule正在通过以下行应用于输入@uid
:
<xsl:apply-templates select="@*|node()"/>
属性的默认模板复制文本,就像您已定义模板一样:
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
为了防止这种情况被应用,请更改apply-templates
选择属性,使其不适用于属性,或为任何属性定义新的空白模板,因此:
<xsl:template match="@*" />
您甚至可以更具体,使用类似的模板仅忽略uid
属性,因此:
<xsl:template match="@uid" />
答案 2 :(得分:0)
答案并不像添加新匹配来覆盖@uid
那样极端。您只需要从select
中删除xsl:apply-templates
。
删除了select
的样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="uid">
<xsl:value-of select="generate-id(.)"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
产生以下输出(@uid
会有所不同):
<root uid="d0e1">
<anode uid="d0e3"/>
<anode uid="d0e5"/>
</root>