【问题标题】:XSLT 2.0 dynamic XPATH expressionXSLT 2.0 动态 XPATH 表达式
【发布时间】:2016-01-20 18:04:09
【问题描述】:

我有一个 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>

到目前为止我所拥有的(基于此解决方案XSLT 2.0 XPATH expression with variable):

<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 从映射中生成另一个 XSLT 来完成这项工作?
  • 我需要一个映射文件,因为我有来自不同提供商的不同输入 XML 文件,我认为为所有输入文件制作一次映射文件将是一个很好且可读的解决方案。但我也必须考虑其他解决方案。使用 XSLT 生成另一个 XSLT 听起来不错,我将尝试这个。非常感谢。

标签: xpath xslt-2.0 saxon


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 2021-11-08
    • 2011-06-05
    • 2020-09-22
    • 1970-01-01
    相关资源
    最近更新 更多