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

如何在XSLT工作流中注入XML预处理过滤步骤并复用原有模板

问题

现有一套XSLT与XML处理工作流,从根匹配节点开始触发后续处理。需要在文档处理前注入预处理步骤,在子节点层级过滤数据后再执行原有流程。

当前流程

输入A(xmlA)-> 模板(xslt1)= 输出

预处理需求

输入A(xmlA)-> 过滤无用数据(xmlNEW)-> 模板(xslt1)= 不含过滤数据的输出

由于现有模板数量过多,在后续流程中过滤会导致模板失效,因此必须在处理前完成过滤。已单独实现过滤功能,但尝试用变量和参数调用模板整合时无法正常工作。


示例XML

<?xml version="1.0" encoding="UTF-16"?>
<MultiDocumentLevel>
    <DocumentLevel>
        <OrderLevel>
            <AllowedFormat>
                <HeaderLevel>
                    <HeaderSort>12345</HeaderSort>
                    <HeaderCode>12345</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>9999</HeaderSort>
                    <HeaderCode>9999-1</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>0000</HeaderSort>
                    <HeaderCode>0000</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>8989</HeaderSort>
                    <HeaderCode>8989</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>7777</HeaderSort>
                    <HeaderCode>123</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>123</HeaderSort>
                    <HeaderCode>14</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>1</HeaderSort>
                    <HeaderCode>1</HeaderCode>
                </HeaderLevel>
            </AllowedFormat>
        </OrderLevel>
    </DocumentLevel>
</MultiDocumentLevel>

主模板(xslt1)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="html"/>

    <xsl:template match="/">
        <xsl:apply-templates select="MultiDocumentLevel"/>
    </xsl:template>

    <!-- ****************************************************************************************************************** -->
    <!--        Name:           MultiDocumentLevel                                                                                           -->
    <!--                        Xsl's Main Template - Start of Builder                                                                                           -->
    <!-- ****************************************************************************************************************** -->
    
    <xsl:template match="MultiDocumentLevel">
        <xsl:apply-templates select="DocumentLevel/OrderLevel/AllowedFormat/HeaderLevel"/>
    </xsl:template> 

    <!-- ****************************************************************************************************************** -->
    <!--        Name:           HeaderLevel                                                                                    -->
    <!--                        Xsl's HeaderLevel Template - Process main data                                                 -->
    <!-- ****************************************************************************************************************** -->

    <xsl:template match="HeaderLevel">
        <!-- Process all nodes under HeaderLevel-->  
        <xsl:value-of select="concat(position(),'  -  ',HeaderCode,'  -  ',.)"/><br/>
    </xsl:template> 
    
</xsl:stylesheet>

过滤模板(单独实现)

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" indent="yes"/>

<xsl:variable name="allowedheaders">
    <headers status="AllowedToPrint">
        <HeaderSort printHeader="12345" name="Allowed1"/>
        <HeaderSort printHeader="123" name="Allowed2"/>
        <HeaderSort printHeader="0000" name="Allowed3"/>
    </headers>
</xsl:variable>

    
 <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>   
    
    
    <xsl:template match="/">
            <xsl:apply-templates select="@*|node()" />
    </xsl:template>

    <xsl:template match="HeaderLevel">  
                  <!-- filter the data at headerlevel based on lookup in allowedheaders variable -->
                    <xsl:if test="HeaderSort=msxsl:node-set($allowedheaders)/headers[@status='AllowedToPrint']/HeaderSort/@printHeader 
                    or HeaderCode=msxsl:node-set($allowedheaders)/headers[@status='AllowedToPrint']/HeaderSort/@printHeader">
                    <xsl:copy>
                        <xsl:apply-templates select="@*|node()"/>
                    </xsl:copy>
                </xsl:if>
    </xsl:template> 

</xsl:stylesheet>

期望过滤后的XML(供主模板处理)

<MultiDocumentLevel>
    <DocumentLevel>
        <OrderLevel>
            <AllowedFormat>
                <HeaderLevel>
                    <HeaderSort>12345</HeaderSort>
                    <HeaderCode>12345</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>0000</HeaderSort>
                    <HeaderCode>0000</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>7777</HeaderSort>
                    <HeaderCode>123</HeaderCode>
                </HeaderLevel>
                <HeaderLevel>
                    <HeaderSort>123</HeaderSort>
                    <HeaderCode>14</HeaderCode>
                </HeaderLevel>
            </AllowedFormat>
        </OrderLevel>
    </DocumentLevel>
</MultiDocumentLevel>

解决方案

基于XSLT 1.0特性,提供两种无需修改原有主模板核心逻辑的整合方案:

方法1:导入主模板,修改根模板注入过滤逻辑

创建新的整合XSLT,先执行过滤生成节点集,再将其传递给原有主模板处理,无需修改xslt1文件:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="html"/>

    <!-- 导入原有主模板 -->
    <xsl:import href="xslt1.xsl"/>

    <!-- 过滤规则变量 -->
    <xsl:variable name="allowedheaders">
        <headers status="AllowedToPrint">
            <HeaderSort printHeader="12345" name="Allowed1"/>
            <HeaderSort printHeader="123" name="Allowed2"/>
            <HeaderSort printHeader="0000" name="Allowed3"/>
        </headers>
    </xsl:variable>

    <!-- 覆盖根模板,先过滤再调用原有逻辑 -->
    <xsl:template match="/">
        <!-- 第一步:生成过滤后的XML节点集 -->
        <xsl:variable name="filteredXml">
            <xsl:apply-templates select="@*|node()" mode="filter"/>
        </xsl:variable>

        <!-- 第二步:将过滤后的节点传递给原有主模板处理 -->
        <xsl:apply-templates select="msxsl:node-set($filteredXml)/MultiDocumentLevel"/>
    </xsl:template>

    <!-- 过滤模式:复制所有节点,仅处理HeaderLevel -->
    <xsl:template match="@*|node()" mode="filter">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="filter"/>
        </xsl:copy>
    </xsl:template>

    <!-- 过滤模式下的HeaderLevel:仅保留符合条件的节点 -->
    <xsl:template match="HeaderLevel" mode="filter">
        <xsl:if test="HeaderSort=msxsl:node-set($allowedheaders)/headers[@status='AllowedToPrint']/HeaderSort/@printHeader 
                    or HeaderCode=msxsl:node-set($allowedheaders)/headers[@status='AllowedToPrint']/HeaderSort/@printHeader">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" mode="filter"/>
            </xsl:copy>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

方法2:在主模板中封装过滤命名模板

如果无法导入外部模板,可直接修改主模板的根节点,添加过滤逻辑:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="html"/>

    <!-- 添加过滤变量和命名模板 -->
    <xsl:variable name="allowedheaders">
        <headers status="AllowedToPrint">
            <HeaderSort printHeader="12345" name="Allowed1"/>
            <HeaderSort printHeader="123" name="Allowed2"/>
            <HeaderSort printHeader="0000" name="Allowed3"/>
        </headers>
    </xsl:variable>

    <!-- 过滤用命名模板 -->
    <xsl:template name="filterXml">
        <xsl:param name="inputNode"/>
        <xsl:apply-templates select="$inputNode" mode="filter"/>
    </xsl:template>

    <xsl:template match="@*|node()" mode="filter">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="filter"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="HeaderLevel" mode="filter">
        <xsl:if test="HeaderSort=msxsl:node-set($allowedheaders)/headers[@status='AllowedToPrint']/HeaderSort/@printHeader 
                    or HeaderCode=msxsl:node-set($allowedheaders)/headers[@status='AllowedToPrint']/HeaderSort/@printHeader">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" mode="filter"/>
            </xsl:copy>
        </xsl:if>
    </xsl:template>

    <!-- 修改根模板,先过滤再执行原有逻辑 -->
    <xsl:template match="/">
        <xsl:variable name="filteredXml">
            <xsl:call-template name="filterXml">
                <xsl:with-param name="inputNode" select="."/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:apply-templates select="msxsl:node-set($filteredXml)/MultiDocumentLevel"/>
    </xsl:template>

    <!-- 原有主模板代码保留 -->
    <xsl:template match="MultiDocumentLevel">
        <xsl:apply-templates select="DocumentLevel/OrderLevel/AllowedFormat/HeaderLevel"/>
    </xsl:template> 

    <xsl:template match="HeaderLevel">
        <xsl:value-of select="concat(position(),'  -  ',HeaderCode,'  -  ',.)"/><br/>
    </xsl:template> 
    
</xsl:stylesheet>

关键说明

  • 利用mode属性区分过滤逻辑与原有业务逻辑,避免模板匹配冲突
  • XSLT1.0中需通过msxsl:node-set()将结果树片段转换为可查询的节点集(不同处理器可能对应不同函数,如Saxon的exsl:node-set())
  • 两种方案均无需修改原有主模板的业务代码,仅在入口处注入过滤步骤

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:22:03