如何将节点结构从一个xml复制到另一个具有不同命名空间的节点?

时间:2008-10-30 11:38:12

标签: c# xml

我有两个XML文件,它们有两个不同的XSD架构和不同的命名空间。它们具有相同的子结构。现在我需要将该节点(以及所有子节点)从一个XML文档复制到另一个XML文档。

如果命名空间相同,克隆会这样做。有一个很好的方法吗? (子结构将在稍后改变 - 但将保持相同。)

4 个答案:

答案 0 :(得分:3)

基本上,您需要一个XSL转换,它创建具有相同名称但具有不同命名空间的新元素。

考虑以下输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<test xmlns="http://tempuri.org/ns_old">
    <child attrib="value">text</child>
</test>

现在你需要一个模板,上面写着“复制你看到的所有内容的结构和名称,但是当你在它的时候声明一个新的命名空间”:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:old="http://tempuri.org/ns_old"
>
  <xsl:output method="xml" version="1.0" 
    encoding="UTF-8" indent="yes" omit-xml-declaration="no" 
  />

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

  <xsl:template match="old:*">
    <xsl:element name="{local-name()}" namespace="http://tempuri.org/ns_new">
      <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

当您通过它运行上述XML时,会产生:

<?xml version="1.0" encoding="UTF-8"?>
<test xmlns="http://tempuri.org/ns_new">
  <child attrib="value">text</child>
</test>

您的所有http://tempuri.org/ns_old元素都有效地更改了其命名空间。当您的输入XML同时具有多个命名空间时,XSL最有可能被扩展一点。

答案 1 :(得分:0)

不确定这是否适用,但我在vb.net中使用两个xml文档做了类似的事情:

Private Shared Sub CopyElement(ByVal FromE As Xml.XmlElement, ByVal ToE As Xml.XmlElement)
    CopyElement(FromE, ToE, Nothing)
End Sub
Private Shared Sub CopyElement(ByVal FromE As Xml.XmlElement, ByVal ToE As Xml.XmlElement, ByVal overAttr As Xml.XmlAttributeCollection)
    Dim NewE As Xml.XmlElement
    Dim e As Xml.XmlElement
    NewE = ToE.OwnerDocument.CreateElement(FromE.Name)

    CopyAttributes(FromE, NewE)
    If Not overAttr Is Nothing Then
        OverrideAttributes(overAttr, NewE)
    End If
    For Each e In FromE
        CopyElement(e, NewE, overAttr)
    Next
    ToE.AppendChild(NewE)


End Sub
Private Shared Sub CopyAttributes(ByVal FromE As Xml.XmlElement, ByVal ToE As Xml.XmlElement)
    Dim a As Xml.XmlAttribute
    For Each a In FromE.Attributes
        ToE.SetAttribute(a.Name, a.Value)
    Next
End Sub
Private Shared Sub OverrideAttributes(ByVal AC As Xml.XmlAttributeCollection, ByVal E As Xml.XmlElement)
    Dim a As Xml.XmlAttribute
    For Each a In AC
        If Not E.Attributes.ItemOf(a.Name) Is Nothing Then
            E.SetAttribute(a.Name, a.Value)
        End If
    Next
End Sub

答案 2 :(得分:0)

按照Tomalak的例子(稍加修复),但使用SetAttribute + OuterXml + InnerXml要简单得多 const string xml_str = @“

<?xml version='1.0' encoding='UTF-8'?>
<root>
  <test xmlns='http://tempuri.org/ns_old'>
    <child attrib='value'>text</child>
  </test>
</root>";

“;

public static void RunSnippet()

{

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml_str);

    XmlElement elem = doc.DocumentElement["test"];
    WL( string.Format("[{0}]", elem ) );
    elem.SetAttribute("xmlns", "http://another.namespace.org/");
    WL( elem.OuterXml );

    XmlDocument another_doc = new XmlDocument();
    another_doc.LoadXml("<root/>");
    another_doc.DocumentElement.InnerXml = elem.OuterXml;
    WL( another_doc.DocumentElement.OuterXml );

}

答案 3 :(得分:0)

如果您希望在匹配某个属性时复制节点的所有子元素。您只需复制引用节点的InnerXML并将其设置为等于新节点。

下面这样的东西,我有一个带有文档元素 Root 元素的XML块作为Tablist,我需要在{{下添加新节点1}} TablistRole="Ka"的所有子节点都应与XXX相同:

Ka

所以我只写下面的代码:

<Tablist>
    <Designation Role="XXX">
        <!--<Tab name="x" default="x"/>-->
        <!--<Tab name="y" default="y"/>-->
        <Tab name="r" default="r" />
        <Tab name="rd" default="rd" />
        <Tab name="qq" default="qq" />
        <Tab name="ddd" default="ddd" />
      </Designation>
    <Designation Role="YYY">
        <!--<Tab name="a" default="a"/>-->
        <!--<Tab name="b" default="b"/>-->
        <Tab name="c" default="c" />
        <Tab name="dd" default="dd" />
        <Tab name="ee" default="ee" />
        <Tab name="f" default="f" />
      </Designation>
    </Tablist>