这个问题是从使用XSLT: Change certain attribute values的答案来解决我的情况,但发现它不起作用。
这是我的xml:
<root>
<Element1 id="VEH1">
<Element2 />
</Element1>
<Element1 id="VEH2">
<Element2 />
</Element1>
</root>
这是我的xsl转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@id">
<xsl:attribute name="id">
<xsl:choose>
<xsl:when test=". = VEH1">
<xsl:text>VEH01</xsl:text>
</xsl:when>
<xsl:when test=". = VEH2">
<xsl:text>VEH02</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
我希望输出看起来像:
<?xml version="1.0" encoding="UTF-8"?><root>
<Element1 id="VEH01">
<Element2/>
</Element1>
<Element1 id="VEH02">
<Element2/>
</Element1>
</root>
但属性值保持不变,至少在http://xslttest.appspot.com/,我不知道为什么。感谢
答案 0 :(得分:2)
<xsl:when test=". = VEH1">
<xsl:text>VEH01</xsl:text>
</xsl:when>
<xsl:when test=". = VEH2">
<xsl:text>VEH02</xsl:text>
</xsl:when>
您缺少文字'VEH1'
和'VEH2'
答案 1 :(得分:2)
这个简单,简短且完整的转换不使用任何显式XSLT条件指令:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Element1[starts-with(@id,'VEH')]">
<Element1 id="VEH0{substring-after(@id,'VEH')}">
<xsl:apply-templates select="@*[not(name()='id')]|node()"/>
</Element1>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<root>
<Element1 id="VEH1">
<Element2 />
</Element1>
<Element1 id="VEH2">
<Element2 />
</Element1>
</root>
产生了想要的正确结果:
<root>
<Element1 id="VEH01">
<Element2/>
</Element1>
<Element1 id="VEH02">
<Element2/>
</Element1>
</root>
<强>解释强>:
identity rule 按“原样”复制已选择执行该节点的每个节点。
有一个覆盖模板匹配任何名为Element1
且具有id
属性的元素,其字符串值以字符串“VEH”开头。
该元素将重新创建为具有相同名称的文字结果元素,并且id
属性具有新的所需字符串值。 AVT (属性值模板)用于缩短代码并使其更具可读性。
在这样创建的元素的主体中,模板应用于所有非id
属性和所有子节点 - 这些属性由身份模板匹配并“按原样”复制。 / p>
<强>更新强>:
@wst建议,只有当这个数字是一个数字时,结尾的数字才应该用零填充。
这是稍微修改过的解决方案,适用于这种情况:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"Element1[starts-with(@id,'VEH')
and string-length(@id)=4
and floor(substring(@id,4)) = floor(substring(@id,4))
]">
<Element1 id="VEH0{substring-after(@id,'VEH')}">
<xsl:apply-templates select="@*[not(name()='id')]|node()"/>
</Element1>
</xsl:template>
</xsl:stylesheet>
在此XML文档上应用此转换时:
<root>
<Element1 id="VEH1">
<Element2 />
</Element1>
<Element1 id="VEH2">
<Element2 />
</Element1>
<Element1 id="VEH12">
<Element3 />
</Element1>
</root>
产生了想要的,正确的(关于新添加的要求)结果:
<root>
<Element1 id="VEH01">
<Element2/>
</Element1>
<Element1 id="VEH02">
<Element2/>
</Element1>
<Element1 id="VEH12">
<Element3/>
</Element1>
</root>
答案 2 :(得分:2)
有一种相当简单的方法 - 只需使用此模板:
<xsl:template match="@id[starts-with(.,'VEH')]">
<xsl:attribute name="id">
<xsl:value-of select="concat('VEH',format-number(substring(.,4),'00'))" />
</xsl:attribute>
</xsl:template>
如果需要,您可以进一步限制匹配的谓词 - 如果and (floor(substring(.,4)) = substring(.,4))
之后有任何其他数字,则可以添加VEH
。