首页 > 解决方案 > 如何使用 XSLT 删除特定 xml 元素的命名空间前缀?

问题描述

我可以成功地从所有元素中删除命名空间前缀,但只想从特定元素中删除前缀

我想从 X509Data 元素中删除命名空间前缀:

<?xml version="1.0" encoding="UTF-8"?>
<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
    </xenc:EncryptedKey>
    <ds:X509Data>
        <ds:X509Certificate>AAA=</ds:X509Certificate>
    </ds:X509Data>
</ds:KeyInfo>

至:

<?xml version="1.0" encoding="UTF-8"?>
<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
    </xenc:EncryptedKey>
    <X509Data>
        <ds:X509Certificate>AAA=</ds:X509Certificate>
    </X509Data>
</ds:KeyInfo>

Java代码:

   public class TestXmlTransformer {

        public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException,
                TransformerFactoryConfigurationError, TransformerException {

            InputStream xmlData = new FileInputStream("C:\\Users\\xxxxxx\\Desktop\\spoon\\test1.xml");
            Document xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlData);

            Source stylesource = new StreamSource("C:\\Users\\xxxxxx\\Desktop\\spoon\\test1.xsl");
            Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
            StringWriter stringWriter = new StringWriter();
            transformer.transform(new DOMSource(xmlDocument), new StreamResult(stringWriter));

            System.out.print(stringWriter.toString());
        }
    }

标签: xsltxslt-2.0xslt-3.0

解决方案


要仅从一个特定元素中删除命名空间,您必须使用自己的模板重新创建它(假设您xmlns:ds="http://www.w3.org/2000/09/xmldsig#"在样式表中定义了命名空间):

<xsl:template match="ds:X509Data">
    <xsl:element name="X509Data">
        <xsl:apply-templates select="node()|@*" />
    </xsl:element>
</xsl:template>

输出与身份模板相结合或<xsl:mode on-no-match="shallow-copy"/>根据需要。

所以整个样式表可能看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <xsl:output method="xml" />

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

    <xsl:template match="ds:X509Data">
        <xsl:element name="X509Data">
            <xsl:apply-templates select="node()|@*" />
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

并且它的输出是所期望的:

<?xml version="1.0" encoding="UTF-8"?>
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
  <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
  <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <xenc:EncryptedKey>
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
    </xenc:EncryptedKey>
    <X509Data>
        <ds:X509Certificate>AAA=</ds:X509Certificate>
    </X509Data>
  </ds:KeyInfo>
</xenc:EncryptedData>

推荐阅读