如何使用XSLT修改XML中指定同类元素的属性值?
问题:修改XML中指定元素的属性值
原始XML代码
<caption> <captionStrings> <add name="lion" providerName="xyx"/> <add name="tiger" providerName="yxy"/> <add name="dog" providerName="yxy"/> </captionStrings> </caption>
期望输出XML
<caption> <captionStrings> <add name="lion" providerName="xyx"/> <add name="cat" providerName="yxy"/> <add name="dog" providerName="yxy"/> </captionStrings> </caption>
尝试的XSLT代码(未达到预期)
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="caption/captionStrings/add/@name"> <xsl:attribute name="{name()}">cat</xsl:attribute> </xsl:template> </xsl:stylesheet>
问题分析与解决方案
你当前的XSLT模板会匹配所有add元素的name属性,导致所有name值都被替换为cat,不符合需求。需要精准匹配目标属性——仅修改name="tiger"的add元素的name属性值。
方案一:直接匹配目标属性
修改模板的匹配路径,指定仅匹配name属性值为tiger的add元素的name属性:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <!-- 身份模板:复制所有未被特殊模板匹配的节点和属性 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 仅匹配name="tiger"的add元素的name属性,替换为cat --> <xsl:template match="caption/captionStrings/add[@name='tiger']/@name"> <xsl:attribute name="name">cat</xsl:attribute> </xsl:template> </xsl:stylesheet>
方案二:匹配目标元素后修改属性
也可以先匹配目标add元素,再替换其name属性,同时保留其他属性:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 匹配name="tiger"的add元素 --> <xsl:template match="caption/captionStrings/add[@name='tiger']"> <xsl:copy> <!-- 替换name属性为cat --> <xsl:attribute name="name">cat</xsl:attribute> <!-- 复制除name外的其他属性 --> <xsl:apply-templates select="@*[name()!='name']"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
两种方案都能实现需求,方案一更简洁直接,适合仅修改单个属性的场景。
内容的提问来源于stack exchange,提问作者s.x
相关产品推荐
相关产品推荐

