You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT 1.0映射转换问题:无法读取输入XML数据

问题说明

我们系统定期从客户系统获取XML文件,用XSLT将客户数据结构转换为数据库支持的格式,95%的操作都是直接复制元素数据。客户迁移数据格式时(比如更换录入表单或供应商),需要支持双路径实现平滑切换。为提升可维护性,我们采用仅需插入映射元素、无需新增代码的映射表方案,但当前代码无法读取输入XML中的数据。


现有代码与示例

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" indent="yes"/>
    <!-- Define the mapping within the XSLT -->
    <xsl:variable name="mapping">
        <mapping>
            <entry key="DocumentIdentifier" value1="/FORM/DocNumber" value2=""/>
            <!-- Add more mapping entries as needed -->
        </mapping>
    </xsl:variable>
    <!-- Identity template to copy the rest of the XML as is -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- Template to match the root element and start the transformation -->
    <xsl:template match="/">
        <output>
            <xsl:apply-templates select="$mapping/mapping/entry"/>
        </output>
    </xsl:template>
    <!-- Template to process each mapping entry -->
    <xsl:template match="entry">
        <xsl:variable name="key" select="@key"/>
        <xsl:variable name="value1" select="@value1"/>
        <xsl:message>
            <xsl:text>Processing entry: </xsl:text>
            <xsl:value-of select="$key"/>
            <xsl:text> - Value1: </xsl:text>
            <xsl:value-of select="$value1"/>
        </xsl:message>
        <xsl:element name="{$key}">
            <xsl:value-of select="*[name() = $value1]"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

源XML示例

<?xml version='1.0' encoding='utf-8'?>
<FORM>
    <DocNumber>INV100123</DocNumber>
</FORM>

当前错误输出

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <DocumentIdentifier/>
</output>

问题根源

  1. 上下文错误:处理entry模板时,当前节点是映射表中的entry元素,而非源XML节点,因此*[name() = $value1]无法定位到源数据。
  2. XPath逻辑错误:value1存储的是完整XPath路径,但代码将其当作元素名匹配,逻辑完全错位。
  3. 未保留源XML上下文:未存储源XML的根节点引用,导致无法在映射处理时查询源数据。

修正后的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" indent="yes"/>
    
    <!-- 保存源XML的根节点上下文 -->
    <xsl:variable name="sourceRoot" select="/"/>
    
    <!-- 映射表定义 -->
    <xsl:variable name="mapping">
        <mapping>
            <entry key="DocumentIdentifier" value1="/FORM/DocNumber" value2=""/>
            <!-- 可添加更多映射项 -->
        </mapping>
    </xsl:variable>

    <!-- 处理根节点,生成输出结构 -->
    <xsl:template match="/">
        <output>
            <xsl:apply-templates select="$mapping/mapping/entry"/>
        </output>
    </xsl:template>

    <!-- 处理每个映射条目 -->
    <xsl:template match="entry">
        <xsl:variable name="key" select="@key"/>
        <!-- 优先使用value1,无数据则切换到value2 -->
        <xsl:variable name="targetValue">
            <xsl:choose>
                <xsl:when test="string-length(@value1) > 0 and $sourceRoot{@value1}">
                    <xsl:value-of select="$sourceRoot{@value1}"/>
                </xsl:when>
                <xsl:when test="string-length(@value2) > 0 and $sourceRoot{@value2}">
                    <xsl:value-of select="$sourceRoot{@value2}"/>
                </xsl:when>
                <xsl:otherwise/>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:element name="{$key}">
            <xsl:value-of select="$targetValue"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

关键改进点

  • 保留源XML上下文:用$sourceRoot变量存储源XML根节点,确保查询时能访问到源数据。
  • 动态XPath查询:使用$sourceRoot{@value1}语法(XSLT 1.0节点集扩展实现动态路径查询,若用XSLT 2.0处理器可直接用xsl:evaluate)。
  • 双路径平滑切换:通过xsl:choose优先读取value1,无数据时自动切换到value2,满足客户格式迁移需求。
  • 简化冗余代码:移除无用的标识模板,精简逻辑。

内容的提问来源于stack exchange,提问作者Steve Ostroff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:35:12