【问题标题】:Creating a new XML altogether using XSLT isn't preserving the namespaces on the Output XML使用 XSLT 完全创建新 XML 不会保留输出 XML 上的名称空间
【发布时间】:2017-10-22 19:29:11
【问题描述】:

我正在尝试将输入 XML 完全转换为新的 XML 格式。它没有保留输出 XML 上的命名空间。我尝试了一些来自 SO 的建议,但是由于我正在创建新的根元素,因此它没有保留命名空间。任何帮助深表感谢!提前致谢!

输入的 XML 是:

<Container
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://hgkl.kj.com">
 <Request>
  <Id>Guid</Id>
  <Name>ABC</Name>
 </Request>
</Container>

XSLT:

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


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

 <xsl:template match="/*"> 
   <xsl:variable name="root" select="name()" />
   <xsl:element name="{$root}">
      <xsl:apply-templates select="child::*"/>
   </xsl:element>
 </xsl:template>

<xsl:template match="child::*"> 
  <xsl:element name="Input">
    // rest of the logic
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<Container>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://hgkl.kj.com">
 <Input>
    // rest of the logic for forming the element
  </Input>
</Container>

XML 中的根标记和其他标记是动态的。转换背后的主要目标是根据字典 xml 中的值将传入的 XML 元素和属性转换为另一种语言 [如:西班牙语]。类似于post

【问题讨论】:

  • 您的输入 XML 和预期的输出 XML 格式不正确。

标签: xslt xml-namespaces


【解决方案1】:

首先,关于所提出的问题。

您的输入有一个文本节点阅读

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://hgkl.kj.com">

作为输入的子级。它不会传播到输出,因为最外层元素的模板(带有match="/*")仅将模板应用于子元素。如果你改变了

  <xsl:apply-templates select="child::*"/> 

在该模板中

  <xsl:apply-templates/>

输出如您所见。

其次,关于你可能有意提出的问题。

如果我们假设示例输入和输出中第一行末尾的 > 是错误的,那么输入和输出文档应该具有命名空间声明绑定前缀 xsdxsi 并且默认命名空间,那么您获得的输出没有命名空间声明,因为您指定输出包含一个具有由$root 给出的 QName 的元素,在这种情况下其值为 Container

如果您希望输出元素具有相同的扩展名称,请替换

<xsl:element name="{$root}">
  ...
</

<xsl:copy>
  ...
</

【讨论】:

  • 是的!第一行末尾的 > 是一个错误。
  • @MukundKn 在这种情况下,读者可以友好地编辑您的问题并修正错字。
  • 完成...谢谢!
【解决方案2】:

如果您的输入 XML 具有默认名称空间,则相关的 XSL 样式表必须定义名称空间前缀并使用 xsl:template 的 @match 属性,只要您使用 XSLT 1.0。因此,以下 XSLT 样式表将满足您的要求:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ins="http://hgkl.kj.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    >

    <xsl:output  indent="yes"/>

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

    <xsl:template match="/ins:*"> 
        <xsl:variable name="root" select="local-name()"/>
        <xsl:element name="{$root}" namespace="http://hgkl.kj.com">
            <xsl:for-each select="namespace::node()">
                <xsl:copy/>
            </xsl:for-each>
            <xsl:apply-templates select="child::*"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="ins:*"> 
        <xsl:element name="Input" namespace="http://hgkl.kj.com">
            // rest of the logic
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

[结果]

<?xml version="1.0" encoding="utf-8"?>
<Container xmlns="http://hgkl.kj.com" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <Input>
    // rest of the logic
   </Input>
</Container>

【讨论】:

  • 感谢您的帮助。但是,即使在 XSL 中定义默认名称空间后,输出中也不存在默认名称空间。喜欢link
  • 您的链接在 xsl:element 上不包含 @namespace 属性。
  • 在我的示例中,我只包含了 xmlns:xsd="w3.org/2001/XMLSchema" xmlns:xsi="w3.org/2001/XMLSchema-instance" 命名空间。我必须为 /xsi:* 编写模板匹配吗?不过,这个 namspace 的事情让我有点困惑
  • 是的,只要你需要使用xsl:element指令,@namespace属性对于生成属于(默认)命名空间的元素是必不可少的。否则生成的元素属于无命名空间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-02
  • 1970-01-01
  • 2018-06-25
相关资源
最近更新 更多