没有命名空间的XSLT复制节点

时间:2014-11-11 21:15:44

标签: xml xslt

(XML版本=" 1.0")我对XSLT很陌生。我得到了以下XML:

<SNAPSHOTS>
  <SNAPSHOT>
    <ID>1</ID>
    <STATUS>COM</STATUS>
  </SNAPSHOT>
  <SNAPSHOT>
    <ID>2</ID>
    <STATUS>ACC</STATUS>
  </SNAPSHOT>
</SNAPSHOTS>

根据我的要求,我设法将提供的XML转换为包含在<DC>根元素中,并在<SNAPSHOTS>元素之前包含标题。

<?xml version="1.0" encoding="utf-8"?>
<DC>
  <Header>
    <FileName>TEST.xml</FileName>
    <NoOfRecords>2</NoOfRecords>
  </Header>

  <SNAPSHOTS>
    <SNAPSHOT>
      <ID>1</ID>
      <STATUS>COM</STATUS>
    </SNAPSHOT>
    <SNAPSHOT>
      <ID>2</ID>
      <STATUS>ACC</STATUS>
    </SNAPSHOT>
  </SNAPSHOTS>
<DC>

这是我创建的XSD:

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

    <xsl:template match="/">
        <DC>
         <Header>
            <FileName>TEST.xml</FileName>
            <NoOfRecords><xsl:value-of select="count(SNAPSHOTS/SNAPSHOT)"/></NoOfRecords>
         </Header>
        <xsl:apply-templates select="node()"/>
        </DC>
    </xsl:template>

    <xsl:strip-space elements="*"/>

     <xsl:template match="node()" name="removeNode">
         <xsl:copy>
           <xsl:apply-templates select="node()"/>
         </xsl:copy>
     </xsl:template>

 </xsl:stylesheet>

当我将命名空间包含到<DC>时,命名空间也会被复制到节点。

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

        <xsl:template match="/">
            <DC xmlns="http://TEST/TEST.xsd"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"> <<-- NAMESPACE ADDED
             <Header>
                <FileName>TEST.xml</FileName>
                <NoOfRecords><xsl:value-of select="count(SNAPSHOTS/SNAPSHOT)"/></NoOfRecords>
             </Header>
            <xsl:apply-templates select="node()"/>
            </DC>

输出:

<?xml version="1.0" encoding="utf-8"?>
<DC xmlns="http://TEST/TEST.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <Header>
    <FileName>TEST.xml</FileName>
    <NoOfRecords>2</NoOfRecords>
  </Header>

  <SNAPSHOTS xmlns="">    <<--INCORRECT
    <SNAPSHOT>
      <ID>1</ID>
      <STATUS>COM</STATUS>
    </SNAPSHOT>
    <SNAPSHOT>
      <ID>2</ID>
      <STATUS>ACC</STATUS>
    </SNAPSHOT>
  </SNAPSHOTS>
<DC>

我尝试了很多解决方案(谷歌搜索&#39;没有命名空间的XSLT复制节点&#39;等等)。我试过的方法之一是以下(xsl copy nodes without xmlns),但它没有删除xmlns =&#34;&#34;

<xsl:apply-templates select="*"  mode="copy-no-namespaces"/>

<xsl:template match="*" mode="copy-no-namespaces">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
    </xsl:element>
</xsl:template>

我还阅读了以下内容,但并不完全理解接受的答案。 enter link description here

我一直在研究这个问题已经有好几个小时了,显然有些东西我还没有得到。对不起,如果我错过了一些简单的事情,考虑到以前提出的类似问题!非常感谢您提供的任何帮助!托马斯

2 个答案:

答案 0 :(得分:2)

在输入XML中,SNAPSHOTS节点和所有后代节点不属于任何命名空间。在XSLT中,您要向DC添加默认命名空间,但是然后从没有命名空间的输入中复制SNAPSHOTS,因此必须添加xmlns=''以显示{ {1}}不在任何名称空间中。没有它,这意味着SNAPSHOTS是您为SNAPSHOTS添加的默认命名空间的一部分。

现在,假设你想要你的输出:

DC

然后,不是按原样复制<DC xmlns="http://TEST/TEST.xsd"> <Header> <FileName>TEST.xml</FileName> <NoOfRecords>2</NoOfRecords> </Header> <SNAPSHOTS> <SNAPSHOT> <ID>1</ID> <STATUS>COM</STATUS> </SNAPSHOT> <SNAPSHOT> <ID>2</ID> <STATUS>ACC</STATUS> </SNAPSHOT> </SNAPSHOTS> </DC> 节点,而是创建具有相同本地名称但属于同一名称空间的新节点。

试试这个XSLT

SNAPSHOTS

请注意,<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes" /> <xsl:strip-space elements="*"/> <xsl:template match="/"> <DC xmlns="http://TEST/TEST.xsd"> <Header> <FileName>TEST.xml</FileName> <NoOfRecords><xsl:value-of select="count(SNAPSHOTS/SNAPSHOT)"/></NoOfRecords> </Header> <xsl:apply-templates select="node()"/> </DC> </xsl:template> <xsl:template match="*" name="removeNode"> <xsl:element name="{local-name()}" namespace="http://TEST/TEST.xsd"> <xsl:apply-templates select="node()"/> </xsl:element> </xsl:template> </xsl:stylesheet> 现在是SNAPSHOTS的一部分,因此与输入中的http://TEST/TEST.xsd不同,后者不是命名空间的一部分。

另一方面,也许SNAPSHOTS不应该是命名空间的一部分?在这种情况下,您可以尝试使用名称空间前缀,如下所示:

SNAPSHOTS

这应输出以下内容

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

    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <t:DC xmlns:t="http://TEST/TEST.xsd">
         <t:Header>
            <t:FileName>TEST.xml</t:FileName>
            <t:NoOfRecords><xsl:value-of select="count(SNAPSHOTS/SNAPSHOT)"/></t:NoOfRecords>
         </t:Header>
        <xsl:apply-templates select="node()"/>
        </t:DC>
    </xsl:template>

     <xsl:template match="node()" name="removeNode">
         <xsl:copy>
           <xsl:apply-templates select="node()"/>
         </xsl:copy>
     </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

问题如下:在一个输出元素(DC,一个新创建的元素)上声明一个默认命名空间,但不在它内部的元素(SNAPSHOT等等)上声明默认命名空间,它们是从输入XML中检索)。 XSLT处理器被迫假设您打算在这个默认名称空间中说明内部的元素

如果您还在输入XML的其余元素上声明了相同的默认命名空间:

<xsl:template match="*" name="removeNode">
   <xsl:element name="{name()}" xmlns="http://TEST/TEST.xsd">

命名空间未声明消失。对我来说,仍然不清楚为什么你需要在DC元素上声明这两个名称空间。

<强>样式表

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

    <xsl:template match="/">
        <DC xmlns="http://TEST/TEST.xsd"
                xmlns:xs="http://www.w3.org/2001/XMLSchema">
         <Header>
            <FileName>TEST.xml</FileName>
            <NoOfRecords><xsl:value-of select="count(SNAPSHOTS/SNAPSHOT)"/></NoOfRecords>
         </Header>
        <xsl:apply-templates select="node()"/>
        </DC>
    </xsl:template>

    <xsl:strip-space elements="*"/>

     <xsl:template match="*" name="removeNode">
         <xsl:element name="{name()}" xmlns="http://TEST/TEST.xsd">
           <xsl:apply-templates/>
         </xsl:element>
     </xsl:template>

 </xsl:stylesheet>

XML输出

<?xml version="1.0" encoding="utf-8"?>
<DC xmlns="http://TEST/TEST.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <Header>
      <FileName>TEST.xml</FileName>
      <NoOfRecords>2</NoOfRecords>
   </Header>
   <SNAPSHOTS>
      <SNAPSHOT>
         <ID>1</ID>
         <STATUS>COM</STATUS>
      </SNAPSHOT>
      <SNAPSHOT>
         <ID>2</ID>
         <STATUS>ACC</STATUS>
      </SNAPSHOT>
   </SNAPSHOTS>
</DC>