如何用XSLT对比XML文档父子元素并筛选差异内容
问题:对比两个XML文档并提取内容不同的
<trans-unit>元素 需求说明
现有两个XML文档(未翻译版、已翻译版),结构均为<body>下包含<trans-unit>元素,每个<trans-unit>有id属性和<source>子元素。需要:
- 仅输出两个文档中同一
id对应的<source>内容不同的<trans-unit>(如已翻译文件中的Id b) - 排除
<source>内容相同的条目(如Id a) - 忽略仅存在于单个文档的条目(如未翻译文件中的Id c)
未翻译文件(original.xml)
<body> <trans-unit id="Id a" maxwidth="240" size-unit="char"> <source>original a</source> </trans-unit> <trans-unit id="Id b" maxwidth="240" size-unit="char"> <source>original b</source> </trans-unit> <trans-unit id="Id c" maxwidth="240" size-unit="char"> <source>original c</source> </trans-unit> </body>
已翻译文件(translatedfile.xml)
<body> <trans-unit id="Id a" maxwidth="240" size-unit="char"> <source>original a</source> </trans-unit> <trans-unit id="Id b" maxwidth="240" size-unit="char"> <source>translated b</source> </trans-unit> </body>
期望输出
<body> <trans-unit id="Id b" maxwidth="240" size-unit="char"> <source>translated b</source> </trans-unit> </body>
现有XSLT代码(存在逻辑问题)
<?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" version="1.0" encoding="utf-8" indent="yes"/> <xsl:variable name="mytranslatedfile" select="document('translatedfile.xml')" /> <xsl:variable name="translated" select="$mytranslatedfile/trans-unit/id" /> <xsl:template match="trans-unit/source"> <xsl:choose> <!----- if the id is the same between the documents ------> <xsl:when test="$translated[ancestor::trans-unit[1]/@id]"> <!----- add an additional test here to compare the source? unsure how to do this ------> <!----- I want to output the trans-unit element and child source element here ------> <P> <xsl:value-of select="."/> </P> </xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet>
解决方案XSLT代码
<?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" version="1.0" encoding="utf-8" indent="yes"/> <!-- 加载已翻译文件 --> <xsl:variable name="translatedDoc" select="document('translatedfile.xml')"/> <!-- 匹配根节点,构建输出的<body> --> <xsl:template match="/body"> <body> <!-- 遍历已翻译文件中的所有trans-unit --> <xsl:for-each select="$translatedDoc/body/trans-unit"> <xsl:variable name="currentId" select="@id"/> <!-- 找到未翻译文件中对应id的trans-unit --> <xsl:variable name="originalUnit" select="/body/trans-unit[@id = $currentId]"/> <!-- 仅当对应id存在,且source内容不同时输出 --> <xsl:if test="$originalUnit and $originalUnit/source != source"> <xsl:copy-of select="."/> </xsl:if> </xsl:for-each> </body> </xsl:template> <!-- 忽略其他默认匹配 --> <xsl:template match="text()"/> </xsl:stylesheet>
逻辑说明
- 通过
document()函数加载已翻译文件,作为对比数据源 - 从已翻译文件的
<body>节点开始遍历所有<trans-unit>,确保输出的是已翻译后的版本 - 对每个已翻译条目,用其
id在未翻译文件中查找对应条目 - 仅满足两个条件时才输出:未翻译文件存在相同
id的条目,且两者<source>内容不一致 - 自动过滤仅存在于单个文档的条目
内容的提问来源于stack exchange,提问作者RM_EM2LQyOngoArEZj
相关产品推荐
相关产品推荐

