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

Java中使用Saxon XSLT API如何正确实现数组过滤?

问题描述

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<Document>
    <tag-one>
        <tag-two>
            <tag-three>
                <tag-four>
                    <tag-five>
                        <tag-six>
                            <tag-seven>
                                <tag-eight>
                                    <tag-nine>
                                        <id-tag>valid_id</id-tag>
                                    </tag-nine>
                                </tag-eight>
                            </tag-seven>
                        </tag-six>
                    </tag-five>
                </tag-four>
            </tag-three>
        </tag-two>
        <tag-two>
            <tag-three>
                <tag-four>
                    <tag-five>
                        <tag-six>
                            <tag-seven>
                                <tag-eight>
                                    <tag-nine>
                                        <id-tag>invalid_id-invalid_kg</id-tag>
                                    </tag-nine>
                                </tag-eight>
                            </tag-seven>
                        </tag-six>
                    </tag-five>
                </tag-four>
            </tag-three>
        </tag-two>
    </tag-one>
</Document>

当前使用的XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        exclude-result-prefixes="#all"
        version="3.0">

    <xsl:param name="invalidIds"/>

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

    <xsl:template match="tag-two[contains($invalidIds, tag-three/tag-four/tag-five//*[local-name()='id-tag'])]">
    </xsl:template>

</xsl:transform>

Java端参数传递代码

List<String> idList = Arrays.asList("invalid_id-invalid_kg");
// 省略其余代码
// Map.of(new QName("invalidIds"), new XdmAtomicValue(idList.toString()))

问题现象

XSLT中打印invalidIds的值为[invalid_id-invalid_kg],导致两个<tag-two>都被过滤。原因是用contains做字符串匹配时,valid_id里的id子串出现在invalid_id-invalid_kg中,误触发了过滤逻辑。


解决方案

1. 修正Java端参数传递

不要把List转成字符串传递,直接传递XdmSequence类型的序列,让XSLT拿到真正的字符串集合:

List<XdmAtomicValue> xdmIds = idList.stream()
    .map(XdmAtomicValue::new)
    .collect(Collectors.toList());
XdmSequence invalidIdsParam = new XdmSequence(xdmIds);
// 传递参数时使用这个XdmSequence对象
Map.of(new QName("invalidIds"), invalidIdsParam);

2. 调整XSLT的匹配逻辑

先把参数声明为字符串序列类型,再用index-of判断ID是否在无效列表中:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        exclude-result-prefixes="#all"
        version="3.0">

    <!-- 明确参数为字符串序列类型 -->
    <xsl:param name="invalidIds" as="xs:string*"/>

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

    <!-- 用index-of判断id是否存在于无效列表,存在则过滤该tag-two -->
    <xsl:template match="tag-two[index-of($invalidIds, tag-three/tag-four/tag-five/tag-six/tag-seven/tag-eight/tag-nine/id-tag) ne ()]">
    </xsl:template>

</xsl:transform>

备选方案(字符串拼接方式,不推荐)

如果必须用字符串传递参数,可以用特殊分隔符(比如|)拼接ID列表,再在XSLT中拆分后判断:

  • Java端拼接:
String invalidIdsStr = String.join("|", idList);
// 传递这个拼接后的字符串
Map.of(new QName("invalidIds"), new XdmAtomicValue(invalidIdsStr));
  • XSLT端处理:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        exclude-result-prefixes="#all"
        version="3.0">

    <xsl:param name="invalidIds"/>
    <!-- 拆分字符串为序列 -->
    <xsl:variable name="invalidIdList" as="xs:string*" select="tokenize($invalidIds, '\|')"/>

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

    <xsl:template match="tag-two[index-of($invalidIdList, tag-three/tag-four/tag-five/tag-six/tag-seven/tag-eight/tag-nine/id-tag) ne ()]">
    </xsl:template>

</xsl:transform>

注意:这种方式要求ID中不能包含你用的分隔符,否则会拆分错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:07:32