【问题标题】:Retaining name space in XML after XSLT transformXSLT 转换后在 XML 中保留名称空间
【发布时间】:2019-02-15 11:11:14
【问题描述】:

这是我的输入 XML

<?xml version="1.0"?>
<myroot xmlns="http://www.myroot.com/v0.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <A>TestProject1</A>
 <B>ValueB</B>

</myroot>

我想将默认命名空间更改为 0.2 并通过 XSLT 转换添加一些新属性。我能够做到这一点,但在我的输出 xml 中,旧的命名空间别名不会像 xmlns:xsd 和 xmlns:xsi 那样保留。

有人指出我的 xslt 出了什么问题。

这是我的 XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:previous="http://www.myroot.com/v0.1">    
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
 <xsl:template match="node()|@*">
<!-- Copy the current node -->
<xsl:copy >
   <!-- Including any attributes it has and any child nodes -->
  <xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="previous:myroot">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
        <xsl:element name="NewElement">1234</xsl:element>
    </xsl:copy>

</xsl:template>

<xsl:template
    match="//*[namespace-uri()='http://www.myroot.com/v0.1']">
    <xsl:element name="{local-name()}"
                 namespace="http://www.myroot.com/v0.2">
        <xsl:apply-templates select="@*|node()" />
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

这是输出 xml(缺少 xsi 和 xsd 命名空间)

<?xml version="1.0"?>
<myroot xmlns="http://www.myroot.com/v0.2" >
 <A>TestProject1</A>
 <B>ValueB</B>
  <NewElement>1234</NewElement>
</myroot>

但 * 预期输出是

<?xml version="1.0"?>
<myroot xmlns="http://www.myroot.com/v0.1" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <A>TestProject1</A>
 <B>ValueB</B>
 <NewElement>1234</NewElement>
</myroot>

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    一种解决方案可以是:(稍微优化

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:previous="http://www.myroot.com/v0.1"
    xmlns:new="http://www.myroot.com/v0.2"
    version="1.0">
    
    <xsl:output method="xml" indent="yes" />
    
    
    <xsl:template match="previous:*">
    
     <xsl:element name="{local-name()}" namespace="http://www.myroot.com/v0.2">
        <xsl:copy-of select="@* | namespace::*[not(. = 'http://www.myroot.com/v0.1')]"/>
            <xsl:choose>
                <xsl:when test="local-name() = 'myroot'">
                    <xsl:element name="NewElement">1234</xsl:element>
                    <xsl:apply-templates/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/bFN1y8X/6

    【讨论】:

      【解决方案2】:

      我建议显式复制命名空间节点:

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          xmlns:previous="http://www.myroot.com/v0.1"
          version="1.0">
      
      <xsl:template match="previous:*">
          <xsl:element name="{local-name()}" namespace="http://www.myroot.com/v0.2">
              <xsl:copy-of select="@* | namespace::*[not(. = 'http://www.myroot.com/v0.1')]"/>
              <xsl:apply-templates/>
          </xsl:element>
      </xsl:template>
      
      </xsl:stylesheet>
      

      https://xsltfiddle.liberty-development.net/bFN1y8X

      如果您想在某个元素(如根元素)中添加新元素,请为此添加一个额外的模板。如果您需要将新命名空间用于所有结果元素,也可以将新命名空间移动到样式表的根元素:

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          xmlns:previous="http://www.myroot.com/v0.1"
          exclude-result-prefixes="previous"
          xmlns="http://www.myroot.com/v0.2"
          version="1.0">
      
      <xsl:output indent="yes"/>
      
      <xsl:template match="previous:*">
          <xsl:element name="{local-name()}">
              <xsl:copy-of select="@* | namespace::*[not(. = 'http://www.myroot.com/v0.1')]"/>
              <xsl:apply-templates/>
          </xsl:element>
      </xsl:template>
      
      <xsl:template match="/previous:*">
          <xsl:element name="{local-name()}">
              <xsl:copy-of select="@* | namespace::*[not(. = 'http://www.myroot.com/v0.1')]"/>
              <xsl:apply-templates/>
              <NewElement>1234</NewElement>
          </xsl:element>
      </xsl:template>
      
      </xsl:stylesheet>
      

      https://xsltfiddle.liberty-development.net/bFN1y8X/4

      【讨论】:

      • 谢谢,但是我新添加的方法有空白命名空间,而其他方法有新的,我只想要根元素的命名空间,现在也是 0.1。检查这个xsltfiddle.liberty-development.net/bFN1y8X/1
      • 是否要将输入命名空间http://www.myroot.com/v0.1 中的myroot 元素转换为新命名空间http://www.myroot.com/v0.2?请编辑您的问题并向我们展示您想要创建的确切结果。
      • 我添加了预期的输出
      • @TRS,我添加了第二个示例,它为输入的根添加了一个新模板,将其转换为命名空间,确保复制任何其他命名空间并添加新元素。
      猜你喜欢
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-16
      • 2012-02-09
      • 1970-01-01
      相关资源
      最近更新 更多