在XML

时间:2019-04-23 22:15:31

标签: xslt xslt-1.0 xslt-grouping

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

  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>

OR

<?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不变的情况下插入名称空间。

4 个答案:

答案 0 :(得分:0)

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

<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>

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

答案 1 :(得分:0)

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

<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>

答案 2 :(得分:0)

极简主义版本:

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::*"/>

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