从子节点去重后填充新元素的XSLT实现咨询
从子节点去重后填充新元素的XSLT实现咨询
看起来你想要处理XML里的重复子节点,提取出<Color>的唯一值,然后为每个唯一值生成新的元素对吧?我来给你整理一个完整的XSLT实现方案,结合你给出的输入XML来演示~
首先先明确你的输入XML(我帮你整理成更清晰的格式):
<Invoice> <InvoiceNumber>99-99</InvoiceNumber> <Customer>ACME</Customer> <Lines> <Line> <LineNumber> 1 </LineNumber> <Color> Blue </Color> </Line> <Line> <LineNumber> 1 </LineNumber> <Color> Blue </Color> </Line> <Line> <LineNumber> 1 </LineNumber> <Color> Red </Color> </Line> <Line> <LineNumber> 1 </LineNumber> <Color> Yellow</Color> </Line> </Lines> </Invoice>
接下来是实现去重并生成新元素的XSLT代码,这里我们用<xsl:key>来高效实现节点分组去重,这是XSLT里处理去重的常用方法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义key,以Color的文本内容作为分组键,注意normalize-space去除前后空格 --> <xsl:key name="distinct-colors" match="Line/Color" use="normalize-space(.)"/> <xsl:template match="/Invoice"> <Invoice> <!-- 保留原有的InvoiceNumber和Customer元素 --> <xsl:copy-of select="InvoiceNumber | Customer"/> <!-- 新增一个DistinctColors节点来存放去重后的颜色 --> <DistinctColors> <!-- 遍历所有符合key条件的Color节点,只取每个分组的第一个节点 --> <xsl:for-each select="Lines/Line/Color[generate-id() = generate-id(key('distinct-colors', normalize-space(.))[1])]"> <!-- 生成新的Color元素,内容是去除空格后的颜色值 --> <Color> <xsl:value-of select="normalize-space(.)"/> </Color> </xsl:for-each> </DistinctColors> <!-- 如果需要保留原有的Lines节点,可以取消下面这行注释 --> <!-- <xsl:copy-of select="Lines"/> --> </Invoice> </xsl:template> </xsl:stylesheet>
代码说明:
<xsl:key>:定义了一个名为distinct-colors的键,匹配所有Line/Color节点,用去除前后空格后的颜色文本作为分组依据,这样能避免因为空格导致的重复判断错误(比如你的示例里有的Color前后有空格)。<xsl:for-each>:筛选出每个颜色分组里的第一个节点,通过generate-id()来判断是否是分组的首个节点,这样就实现了去重。- 我们保留了原XML里的
<InvoiceNumber>和<Customer>,同时新增了<DistinctColors>节点,里面存放每个唯一的<Color>元素。
转换后的输出XML效果:
<Invoice> <InvoiceNumber>99-99</InvoiceNumber> <Customer>ACME</Customer> <DistinctColors> <Color>Blue</Color> <Color>Red</Color> <Color>Yellow</Color> </DistinctColors> </Invoice>
如果你的需求是要在其他位置生成新元素,或者有其他调整,只需要修改模板里的节点结构就可以啦~
备注:内容来源于stack exchange,提问作者TheUltimateHack
相关产品推荐
相关产品推荐

