XSLT 2.0 动态 XPATH 表达式

XSLT 2.0 dynamic XPATH expression

我有一个 XML 文件需要基于 XSLT 2.0 映射文件进行转换。我正在使用 Saxon HE 处理器。

我的映射文件:

<element root="TEST">
    <childName condition="/TEST/MyElement/CHILD[text()='B']>/TEST/MyElement/CHILD</childName>
    <childBez condition="/TEST/MyElement/CHILD[text()='B']>/TEST/MyElement/CHILDBEZ</childBez>
</element>

当 CHILD 的文本等于 B 时,我必须复制元素 CHILD 和 CHILDBEZ 以及父元素和根元素。 所以有了这个输入:

<?xml version="1.0" encoding="UTF-8"?>
<TEST>
    <MyElement>
        <CHILD>A</CHILD>
        <CHILDBEZ>ABEZ</CHILDBEZ>
        <NotInteresting></NotInteresting>
    </MyElement>
    <MyElement>
        <CHILD>B</CHILD>
        <CHILDBEZ>BBEZ</CHILDBEZ>
        <NotInteresting2></NotInteresting2>
    </MyElement>
</TEST>

所需的输出:

<TEST>
    <MyElement>
        <childName>B</childName>
        <childBez>BBEZ</childBez>
    </MyElement>
</TEST>

到目前为止我有什么(基于这个解决方案):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    
<xsl:strip-space elements="*"/>

<xsl:param name="mapping" select="document('mapping.xml')"/>

<xsl:key name="map" match="*" use="."/>

<xsl:template match="/">
    <xsl:variable name="first-pass">
        <xsl:apply-templates mode="first-pass"/>
    </xsl:variable>
    <xsl:apply-templates select="$first-pass/*"/>
</xsl:template>

<xsl:template match="*" mode="first-pass">
    <xsl:param name="parent-path" tunnel="yes"/>
    <xsl:variable name="path" select="concat($parent-path, '/', name())"/>
    <xsl:variable name="replacement" select="key('map', $path, $mapping)"/>
    <xsl:variable name="condition" select="key('map', $path, $mapping)/@condition"/>        
    <xsl:choose>
        <xsl:when test="$condition!= ''">
            <!-- if there is a condition defined in the mapping file, check for it -->
        </xsl:when>
        <xsl:otherwise>
            <xsl:element name="{if ($replacement) then name($replacement) else name()}">
                <xsl:attribute name="original" select="not($replacement)"/>
                <xsl:apply-templates mode="first-pass">
                    <xsl:with-param name="parent-path" select="$path" tunnel="yes"/>
                </xsl:apply-templates>
            </xsl:element>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template>

<xsl:template match="*">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[@original='true' and not(descendant::*/@original='false')]"/>    
</xsl:stylesheet>

但问题是无法使用 XSLT 2.0 评估动态 XPATH 表达式。有谁知道解决方法吗?另外我的映射文件有问题。当其中只有一个元素时,它根本不起作用。

如果动态 XPath 评估不是您所选处理器的一个选项,那么生成 XSLT 样式表通常是一个不错的选择。事实上,它通常是一个不错的选择。

一种思考方式是,您的映射文件实际上是一个用非常简单的转换语言编写的程序。有两种执行该程序的方法:您可以编写一个解释器(动态 XPath 评估),或者您可以编写一个编译器(XSLT 样式表生成)。两者都很好。