XSLT双命名空间下无法根据子节点值删除整个contactStanza父节点
XSLT父节点过滤删除问题
实现需求
当<contactStanza>节点的子节点<ns2:contactTypeCode>值不为ABC或DEF时,删除整个<contactStanza>节点的全部内容。现有其余XSLT逻辑均已验证可正常运行,不改动已生效代码,仅调整过滤相关逻辑。
输入XML
<?xml version="1.0" encoding="UTF-8"?> <accountEventNotify xmlns="http://xmlns.example.com/eventNotify/v1" xmlns:ns2="http://xmlns.example.com/cds/customer" schemaVersion="1"> <create> <contactStanza> <ns2:accountContact domain="customer" majorVersion="0" minorVersion="28"> <ns2:contactTypeCode>ABC</ns2:contactTypeCode> </ns2:accountContact> <ns2:contact domain="customer" majorVersion="0" minorVersion="28"> <ns2:companyName>Company A</ns2:companyName> </ns2:contact> </contactStanza> <contactStanza> <ns2:accountContact domain="customer" majorVersion="0" minorVersion="28"> <ns2:contactTypeCode>GHI</ns2:contactTypeCode> </ns2:accountContact> <ns2:contact domain="customer" majorVersion="0" minorVersion="28"> <ns2:companyName>Company B</ns2:companyName> </ns2:contact> </contactStanza> </create> </accountEventNotify>
现有XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://xmlns.example.com/eventNotify" xmlns:v1="http://xmlns.example.com/eventNotify/v1" xpath-default-namespace="http://xmlns.example.com/eventNotify/v1" xmlns:ns2="http://xmlns.example.com/cds/customer" exclude-result-prefixes="v1"> <!-- 移除空行 --> <xsl:output method="xml" encoding="utf-8" indent="yes" /> <xsl:strip-space elements="*" /> <!-- Template #01 替换schemaVersion值 --> <xsl:template match="/*/@schemaVersion"> <xsl:attribute name="{name()}">21.22.35</xsl:attribute> </xsl:template> <!-- Template #02 将命名空间http://xmlns.example.com/eventNotify/v1替换为http://xmlns.example.com/eventNotify --> <xsl:template match="v1:*"> <xsl:element name="{local-name()}"> <xsl:copy-of select="namespace::*[not(. = 'http://xmlns.example.com/eventNotify/v1')]" /> <xsl:apply-templates select="@* | node()" /> </xsl:element> </xsl:template> <!-- Template #03 --> <xsl:template match="ns2:*"> <xsl:copy copy-namespaces="no"> <xsl:copy-of select="namespace::*[not(. = 'http://xmlns.example.com/eventNotify/v1')]" /> <xsl:copy-of select="@*" /> <xsl:apply-templates select="node()" /> </xsl:copy> </xsl:template> <!-- Template #04 当<ns2:contactTypeCode>不是'ABC'/'DEF'时,不输出整个<contactStanza>块 --> <xsl:template match="contactStanza/ns2:accountContact[not(ns2:contactTypeCode = 'ABC' or ns2:contactTypeCode = 'DEF')]" /> </xsl:stylesheet>
注:上述XSLT除Template #04的过滤逻辑外,其余模板均已验证正常工作,无需调整。
当前输出结果
<?xml version="1.0" encoding="UTF-8"?> <accountEventNotify xmlns="http://xmlns.example.com/eventNotify/v1" xmlns:ns2="http://xmlns.example.com/cds/customer" schemaVersion="1"> <create> <contactStanza> <ns2:accountContact domain="customer" majorVersion="0" minorVersion="28"> <ns2:contactTypeCode>ABC</ns2:contactTypeCode> </ns2:accountContact> <ns2:contact domain="customer" majorVersion="0" minorVersion="28"> <ns2:companyName>Company A</ns2:companyName> </ns2:contact> </contactStanza> <contactStanza> <ns2:contact domain="customer" majorVersion="0" minorVersion="28"> <ns2:companyName>Company B</ns2:companyName> </ns2:contact> </contactStanza> </create> </accountEventNotify>
问题描述
- 当前Template #04仅删除了不符合条件的
<ns2:accountContact>节点,未删除整个不符合条件的<contactStanza>节点,该节点下的<ns2:contact>子节点仍然残留,不符合预期。 - 当前编写的过滤模板匹配路径为
contactStanza/ns2:accountContact[not(ns2:contactTypeCode = 'ABC' or ns2:contactTypeCode = 'DEF')],原预期该模板可直接移除整个<contactStanza>块。 - 实际生产场景中
<contactStanza>节点会多次出现,示例仅保留2个节点用于复现问题,初步怀疑问题与XPath路径涉及两个不同命名空间的节点组合有关,需要可行的修复方案。
期望输出结果
<?xml version="1.0" encoding="UTF-8"?> <accountEventNotify xmlns="http://xmlns.example.com/eventNotify/v1" xmlns:ns2="http://xmlns.example.com/cds/customer" schemaVersion="1"> <create> <contactStanza> <ns2:accountContact domain="customer" majorVersion="0" minorVersion="28"> <ns2:contactTypeCode>ABC</ns2:contactTypeCode> </ns2:accountContact> <ns2:contact domain="customer" majorVersion="0" minorVersion="28"> <ns2:companyName>Company A</ns2:companyName> </ns2:contact> </contactStanza> </create> </accountEventNotify>
内容的提问来源于stack exchange,提问作者heisenberg
相关产品推荐
相关产品推荐

