【问题标题】:Inserting static namespace value in the XML在 XML 中插入静态命名空间值
【发布时间】:2019-09-13 03:56:50
【问题描述】:

我正在编写一个 XSLT 脚本,我的目标是插入带有根元素的命名空间 (http://www.COMP.com/upp/readxml/09)。我写了几个变体,我的 2 个代码部分解决了它。

  1. XSLT 代码 AB -- 这个代码插入了命名空间,但所有属性值都被连接起来,并且没有提供任何标签。
  2. XSLT 代码 PQ -- 这个插入了命名空间,但改变了第二个节点的层次结构并将其作为根元素。

代码 AB:

<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:tns="http://www.COMP.com/upp/readxml/09">
    <xsl:output method="xml"/>
    <xsl:template match="*">
        <xsl:variable name="elname">
            <xsl:text disable-output-escaping="yes">tns:</xsl:text>
            <xsl:value-of select="local-name()"/>
        </xsl:variable>     
                <xsl:element name="tns:{local-name()}">
                    <xsl:apply-templates select="@* | node()"/>             
                </xsl:element>
    </xsl:template>
</xsl:stylesheet>

代码PQ:

<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
    <xsl:output method="xml"/>
    <xsl:template match="*" priority="1">
        <xsl:element name="{local-name()}" namespace="http://www.COMP.com/upp/readxml/09">
         <xsl:copy-of copy-namespaces="no" select="*[local-name() != 'RootDocument']"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

输入 XML:

<?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<RootDocument xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
    <System Id="GOLD" />
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z" />
    <Timezone Id="UTC" />   
    <CorrelationID Id="" />
  </Header>
 <Channels> 
    <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A" />     
    </Channel>
  </Channels>
</RootDocument>

预期输出 XML:

<?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<RootDocument xmlns="http://www.COMP.com/upp/readxml/09" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
    <System Id="GOLD" />
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z" />
    <Timezone Id="UTC" />   
    <CorrelationID Id="" />
  </Header>
 <Channels> 
    <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A" />     
    </Channel>
  </Channels>
</RootDocument>

<?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<RootDocument xmlns="http://www.COMP.com/upp/readxml/09">
<Header>
    <System Id="GOLD" />
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z" />
    <Timezone Id="UTC" />   
    <CorrelationID Id="" />
  </Header>
 <Channels> 
    <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A" />     
    </Channel>
  </Channels>
</RootDocument>

您能否建议如何在 XML 中正确获取属性或以任何其他方式插入命名空间,同时保持 XML 的其余部分相同。

【问题讨论】:

  • 您所展示的远非“保持 XML 的其余部分相同”。在您的预期输出中,所有 元素与根元素位于相同的命名空间中 - 因此所有元素都需要以相同方式处理。
  • 请注意,在 XSLT 的数据模型 (XDM) 中,名称空间不是属性;您需要考虑如何为结果树中的元素提供正确的扩展名称(= uri / 本地名称对),而不是如何生成命名空间前缀或命名空间声明。

标签: xslt xslt-1.0 xslt-grouping


【解决方案1】:

您正在将空命名空间中的元素转换为某个固定命名空间。所以这个样式表

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

    <xsl:template match="*[namespace-uri()='']">
        <xsl:element name="{name()}" namespace="http://www.COMP.com/upp/readxml/09">
            <xsl:copy-of select="namespace::*"/>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

输出:

<RootDocument xmlns="http://www.COMP.com/upp/readxml/09"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Header>
    <System Id="GOLD"/>
    <Creation_Datetime Datetime="2019-02-19T17:53:38Z"/>
    <Timezone Id="UTC"/>
    <CorrelationID Id=""/>
  </Header>
  <Channels>
    <Channel StartDate="2019-01-01T00:00:00-05:00" 
             EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
      <ChannelID ID="LC:2A"/>
    </Channel>
  </Channels>
</RootDocument>

请注意namespace 轴自 XPath 2.0 起已弃用,这意味着 “如果 XPath 1.0 兼容模式为 false,则对命名空间轴的支持是实现定义的” em>,因此您可能会得到第二种格式的预期结果。在实践中,我只知道一个 XSLT 处理器不能处理 namespace 轴:Mozilla Firefox 内部 XSLT 处理器,即使它只是一个 XSLT 1.0 处理器,它也是 does not implement the namespace 轴。

【讨论】:

    【解决方案2】:

    您可以使用以下模板来获得所需结果的第二个版本:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="xml"/>
        <xsl:strip-space elements="*" />
    
        <xsl:template match="*">
            <xsl:element name="{local-name()}" namespace="http://www.COMP.com/upp/readxml/09">
              <xsl:apply-templates select="node()|@*" />
            </xsl:element>
        </xsl:template>
    
        <xsl:template match="@*">
            <xsl:copy select="@*" />
        </xsl:template>
    
    </xsl:stylesheet>
    

    输出为:

    <?xml version="1.0"?>
    <RootDocument xmlns="http://www.COMP.com/upp/readxml/09">
        <Header>
            <System Id="GOLD"/>
            <Creation_Datetime Datetime="2019-02-19T17:53:38Z"/>
            <Timezone Id="UTC"/>
            <CorrelationID Id=""/>
        </Header>
        <Channels>
            <Channel StartDate="2019-01-01T00:00:00-05:00" EndDate="2019-02-01T00:00:00-05:00" TimeZone="EasternUS">
                <ChannelID ID="LC:2A"/>
            </Channel>
        </Channels>
    </RootDocument>
    

    【讨论】:

      【解决方案3】:

      极简版:

      XSLT 1.0

      <xsl:stylesheet version="2.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" version="1.0" encoding="us-ascii" standalone="yes" indent="yes"/>
      
      <xsl:template match="*">
          <xsl:element name="{local-name()}" namespace="http://www.COMP.com/upp/readxml/09">
              <xsl:copy-of select="@*"/>
              <xsl:apply-templates/>
          </xsl:element>
      </xsl:template>
      
      </xsl:stylesheet>
      

      这将产生您的问题中显示的第二个结果。要获得第一个输出(带有冗余命名空间声明),请更改:

      <xsl:copy-of select="@*"/>
      

      到:

      <xsl:copy-of select="@* | namespace::*"/>
      

      【讨论】:

        【解决方案4】:

        感谢大家回复我的问题。上述所有解决方案都有效,同时我也在尝试,这就是我开发的,它也给出了预期的结果。

        <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://www.COMP.com/upp/readxml/09">
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:element>
            </xsl:template>
        </xsl:stylesheet>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-12-09
          • 1970-01-01
          • 2021-10-03
          • 1970-01-01
          • 1970-01-01
          • 2023-03-17
          • 2012-01-04
          相关资源
          最近更新 更多