如何使用 XSLT 将名称空间添加到 XML 的根元素?

问题描述 投票:0回答:2

我有一个输入 XML

<Request>
  <Info>
    <Country>US</Country>
    <Part>A</Part>
   </Info>
</Request>

我的输出应该是这样的

<Request
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://hgkl.kj.com">
  <Info>
    <Country>US</Country>
    <Part>A</Part>
  </Info>
</Request>

请让我知道如何添加多个命名空间和默认命名空间,如上面的 XML。

xml xslt xml-parsing
2个回答
28
投票

这是我在 XSLT 2.0 中的做法...

XML 输入

<Request>
    <Info>
        <Country>US</Country>
        <Part>A</Part>
    </Info>
</Request>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="*" priority="1">
        <xsl:element name="{local-name()}" namespace="http://hgkl.kj.com">
            <xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
            <xsl:namespace name="xsd" select="'http://www.w3.org/2001/XMLSchema'"/>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

XML 输出

<Request xmlns="http://hgkl.kj.com"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <Info>
      <Country>US</Country>
      <Part>A</Part>
   </Info>
</Request>

这里有一个 XSLT 1.0 选项,它会产生相同的输出,但要求您知道根元素的名称...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="/Request">
        <Request xmlns="http://hgkl.kj.com" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <xsl:apply-templates select="@*|node()"/>           
        </Request>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{local-name()}" namespace="http://hgkl.kj.com">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

0
投票

这个答案显然没有优化,但会提示您如何让它在 4.2 版本的命名空间和非命名空间 XML 上工作:

这里是

parseXml

的body方法
JAXBContext jc = JAXBContext.newInstance(VAST.class);
Unmarshaller u = jc.createUnmarshaller();

// should be optimized
TransformerFactory tf = TransformerFactory.newInstance();
StringWriter sw = new StringWriter();
URL urlXslt = VastParser.class.getClassLoader().getResource("xslt/vast_4.2.xslt");
File fileXslt = new File(urlXslt.toURI());
Transformer t = tf.newTransformer(new StreamSource(new FileInputStream(fileXslt)));
// transform original XML with XSLT to always add the namespace in the parsing 
t.transform(new StreamSource(new StringReader(xmlString)), new StreamResult(sw));

// unmarshall transformed XML
JAXBElement<VAST> foo = u.unmarshal(new StreamSource(new StringReader(sw.toString())), VAST.class);

return new CustomVast(foo.getValue());

src/main/resources/xslt/vast_4.2.xslt
是:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|text()|comment()|processing-instruction()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- adds the xmlns part to the VAST element -->
    <xsl:template match="/VAST">
        <VAST xmlns="http://www.iab.com/VAST">
            <xsl:apply-templates select="@*|node()"/>
        </VAST>
    </xsl:template>

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

这样,两个单元测试都适用于 4.2 部分。

© www.soinside.com 2019 - 2024. All rights reserved.