使用 XSLT 2.0,如何根据以下规则/要求动态处理 XML 文档以删除具有 xml:lang
属性的节点?
要求:
- 查找具有属性
xml:lang
的任何节点(它是相同类型的直系兄弟姐妹) - 请注意,
xml:lang
值具有基于语言/区域设置的 3 层层次结构,下面提供了非详尽的示例:- X 默认值(第 1 层,最高)
- en (第 2 层,语言前缀,其他值示例:fr、es、ru)
- en-US(第 3 层,语言前缀后跟后缀,其他值示例:en-GB、en-CA)
- 根据已知的层次结构,应删除重复值。
- 删除重复项时,还要考虑同级可能存在的其他属性。
- 保持 XML 文档的其余部分不受干扰
示例数据集:
<?xml version="1.0" encoding="UTF-8"?>
<arbitrarydepth>
<scenario1 xml:lang="x-default">A Default Node Value</scenario1>
<scenario1 xml:lang="en">A Default Node Value</scenario1>
<scenario1 xml:lang="en-US">A Default Node Value</scenario1>
<scenario2 xml:lang="x-default">The orig value</scenario2>
<scenario2 xml:lang="en">The orig value</scenario2>
<scenario2 xml:lang="en-US">A new value</scenario2>
<scenario3 xml:lang="x-default">The orig value</scenario3>
<scenario3 xml:lang="en">A new value</scenario3>
<scenario3 xml:lang="en-US">The orig value</scenario3>
<scenario4 xml:lang="x-default">The orig value</scenario4>
<scenario4 xml:lang="en">An english value</scenario4>
<scenario4 xml:lang="en-US">An english US value</scenario4>
<scenario4 xml:lang="fr">A french value</scenario4>
<scenario4 xml:lang="fr-FR">A french value</scenario4>
<scenario4 xml:lang="fr-CA">A french Canada value</scenario4>
<scenario5 xml:lang="x-default" attr0="something here">The orig value</scenario5>
<scenario5 xml:lang="en" attr1="Some attribute">The orig value</scenario5>
<scenario5 xml:lang="en-US" attr2="some other attribute">The orig value</scenario5>
<scenario5 xml:lang="fr" attr0="something here">The orig value</scenario5>
<scenario5 xml:lang="fr-FR">The orig value</scenario5>
</arbitrarydepth>
示例结果集:
<?xml version="1.0" encoding="UTF-8"?>
<arbitrarydepth>
<scenario1 xml:lang="x-default">A Default Node Value</scenario1>
<scenario2 xml:lang="x-default">The orig value</scenario2>
<scenario2 xml:lang="en-US">A new value</scenario2>
<scenario3 xml:lang="x-default">The orig value</scenario3>
<scenario3 xml:lang="en">A new value</scenario3>
<scenario3 xml:lang="en-US">The orig value</scenario3>
<scenario4 xml:lang="x-default">The orig value</scenario4>
<scenario4 xml:lang="en">An english value</scenario4>
<scenario4 xml:lang="en-US">An english US value</scenario4>
<scenario4 xml:lang="fr">A french value</scenario4>
<scenario4 xml:lang="fr-CA">A french Canada value</scenario4>
<scenario5 xml:lang="x-default" attr0="something here">The orig value</scenario5>
<scenario5 xml:lang="en" attr1="Some attribute">The orig value</scenario5>
<scenario5 xml:lang="en-US" attr2="some other attribute">The orig value</scenario5>
</arbitrarydepth>
这应该满足所有要求,除了最后一个关于匹配动态属性的要求:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="*">
<xsl:variable name="elementName" select="name()"/>
<xsl:variable name="contentText" select="normalize-space(.)"/>
<xsl:choose>
<xsl:when test="not(@xml:lang)">
<!-- Non-lang element -->
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:when>
<xsl:when test="@xml:lang='x-default'">
<!-- Tier 1: xml:lang="x-default" -->
<xsl:copy-of select="."/>
</xsl:when>
<xsl:when test="contains(@xml:lang,'-')">
<!-- Tier 3: xml:lang="en-US" -->
<xsl:variable name="baselang" select="substring-before(@xml:lang, '-')"/>
<xsl:choose>
<xsl:when test="../*[name()=$elementName][@xml:lang=$baselang][normalize-space(.)=$contentText]">
<!-- Same text as Tier 2 parent -->
</xsl:when>
<xsl:when test="../*[name()=$elementName][@xml:lang=$baselang]">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:when test="../*[name()=$elementName][@xml:lang='x-default'][normalize-space(.)=$contentText]">
<!-- Same text as Tier 1 parent -->
</xsl:when>
<xsl:when test="../*[name()=$elementName][@xml:lang='x-default']">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<!-- Tier 2: xml:lang="en" -->
<xsl:choose>
<xsl:when test="../*[name()=$elementName][@xml:lang='x-default'][normalize-space(.)=$contentText]">
<!-- Same text as Tier 1 parent -->
</xsl:when>
<xsl:when test="../*[name()=$elementName][@xml:lang='x-default']">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<!-- No matching parent -->
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
演示:http://www.xsltcake.com/slices/uopn40
匹配父属性和子属性之间的动态属性实际上非常复杂。您必须循环遍历属性并与当前父级进行比较。如果父级上缺少任何属性,或者其值不同,则必须保留新元素。
为了满足最后一个要求,我认为你必须转向命令式语言(C#,JavaScript,Java)。