如何用XSLT从不同XPath提取关联的唯一值?
XSLT提取带关联字段的唯一值
需求:从XML中提取包含cyber、question等关联字段的唯一记录集合,当前使用distinct-values()仅能获取孤立字段值,无法保留对应的关联字段信息。
输入XML示例
<survey> <response> <cyber>malware</cyber> <question>Q1</question> <value>Phishing</value> </response> <response> <cyber>malware</cyber> <question>Q1</question> <value>Phishing</value> </response> <response> <cyber>ransomware</cyber> <question>Q2</question> <value>Data Leak</value> </response> <response> <cyber>malware</cyber> <question>Q3</question> <value>Phishing</value> </response> </survey>
预期输出
<unique-responses> <response> <cyber>malware</cyber> <question>Q1</question> <value>Phishing</value> </response> <response> <cyber>ransomware</cyber> <question>Q2</question> <value>Data Leak</value> </response> <response> <cyber>malware</cyber> <question>Q3</question> <value>Phishing</value> </response> </unique-responses>
尝试过的XSLT代码(仅提取孤立值)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <values> <xsl:value-of select="distinct-values(//response/value)" separator=" "/> </values> </xsl:template> </xsl:stylesheet>
解决方案XSLT代码
XSLT 2.0+ 实现(使用分组)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/survey"> <unique-responses> <!-- 按cyber、question、value组合分组,确保完整记录唯一 --> <xsl:for-each-group select="response" group-by="concat(cyber, '|', question, '|', value)"> <!-- 输出每组的第一条记录,保留所有关联字段 --> <xsl:copy-of select="current-group()[1]"/> </xsl:for-each-group> </unique-responses> </xsl:template> </xsl:stylesheet>
XSLT 1.0 实现(Muenchian分组)
如果环境仅支持XSLT 1.0,使用Muenchian分组法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 定义分组键:组合cyber、question、value确保记录唯一 --> <xsl:key name="unique-response" match="response" use="concat(cyber, '|', question, '|', value)"/> <xsl:template match="/survey"> <unique-responses> <!-- 筛选每组的第一个节点 --> <xsl:for-each select="response[generate-id() = generate-id(key('unique-response', concat(cyber, '|', question, '|', value))[1])]"> <xsl:copy-of select="."/> </xsl:for-each> </unique-responses> </xsl:template> </xsl:stylesheet>
关键说明
- 核心思路是按完整记录的特征组合分组,而非仅提取单个字段的唯一值
- XSLT 2.0+的
<xsl:for-each-group>语法更简洁,直接通过group-by定义分组规则 - XSLT 1.0依赖Muenchian分组,通过
xsl:key和generate-id()筛选唯一组的首节点
内容的提问来源于stack exchange,提问作者Swap
相关产品推荐
相关产品推荐

