XSLT中value-of返回重复元素值问题求助
嘿,我明白你现在的困扰——用XPath提取//Profile/Topic/Attrib[@name='description']的时候,每个Profile对应的这个值总是重复出现对吧?这大概率是因为你的源XML里,单个<Profile>节点下存在多个<Topic>,或者同一个Profile下有多个匹配@name='description'的<Attrib>,导致你的XPath在全局遍历的时候,把同一个Profile的目标值抓了好几次。
下面给你两种实用的解决思路,按需选就行:
1. 精准定位单个Profile下的目标值(纯XPath优化)
如果只是想通过XPath准确提取每个Profile的目标字段,别直接全局搜Attrib,要从单个Profile节点出发去定位子节点:
- 先拿到所有Profile节点:
//Profile - 对每个Profile,逐个提取字段:
- Profile自身的name属性:
@name - orderid属性:
@orderid - status属性:
@status - 订单说明(description):
Topic/Attrib[@name='description']/text() - keywords:
Topic/Attrib[@name='keywords']/text() - 关键词说明:
Topic/Attrib[@name='keywordsDescription']/text()(这个你根据实际的Attrib name调整就行)
- Profile自身的name属性:
要是同一个Profile下有好几个Topic,但你只需要第一个匹配的description,就加个索引限定:Topic[1]/Attrib[@name='description']/text(),这样就只会取第一个符合条件的值,不会重复。
2. 用XSLT生成可控的目标XML(更稳妥的方式)
如果你的最终目的是生成包含指定字段的XML输出,用XSLT来转换会更靠谱,能完全控制每个Profile的输出内容,从根源避免重复。给你写个示例代码:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 匹配根节点,遍历所有Profile --> <xsl:template match="/CustomerExport"> <Profiles> <xsl:for-each select="Profile"> <Profile> <!-- 提取Profile自身的属性 --> <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute> <xsl:attribute name="orderid"><xsl:value-of select="@orderid"/></xsl:attribute> <xsl:attribute name="status"><xsl:value-of select="@status"/></xsl:attribute> <!-- 提取订单说明,加[1]确保只取第一个匹配的 --> <订单说明><xsl:value-of select="Topic/Attrib[@name='description'][1]/text()"/></订单说明> <!-- 提取keywords和关键词说明 --> <keywords><xsl:value-of select="Topic/Attrib[@name='keywords'][1]/text()"/></keywords> <关键词说明><xsl:value-of select="Topic/Attrib[@name='keywordsDescription'][1]/text()"/></关键词说明> </Profile> </xsl:for-each> </Profiles> </xsl:template> </xsl:stylesheet>
这段XSLT会挨个遍历每个<Profile>,为每个Profile生成包含目标字段的节点,每个Profile只会输出一次对应的值。要是某个Profile下有多个匹配的Attrib,[1]会帮你锁定第一个,彻底解决重复问题。
快速排查重复根源的小技巧
你可以先检查下源XML:看看每个<Profile>下到底有多少个<Topic>节点,每个Topic下又有多少个@name='description'的<Attrib>——这就是重复的源头。也可以先测试单个Profile的XPath,比如//Profile[1]/Topic/Attrib[@name='description'],看看返回的节点数量,就能确定是不是多节点导致的重复了。
内容的提问来源于stack exchange,提问作者GLarose

