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

本文关键字:xml 另一个 空间 复制 结构 节点 一个 | 更新日期: 2023-09-27 17:47:46

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

如果名称空间相同,克隆也可以。有什么好方法吗?(子结构稍后将发生变化,但将保持不变。)

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

基本上,您需要一个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很可能必须进行一点扩展。

不确定这是否适用,但我在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

遵循Tomalak的示例(有一点修复),但使用SetAttribute+OuterXml+InnerXml要简单得多const字符串xml_str=@"

<?xml版本="1.0"编码="UTF-8"?><root><测试xmlns='http://tempuri.org/ns_old'><child attrib='value'>文本<child><测试><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 );

}

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

类似于这样,在下面,我有一个XML块,其中DocumentElementRoot元素为Tablist,我需要在Tablist下用Role="Ka"添加新节点,Ka的所有子节点都应该与XXX:相同

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

所以我只写以下代码:

XmlDocument objXmlDocument1 = null;
objXmlDocument1 = new XmlDocument();
objXmlDocument1.Load(
    System.Web.HttpContext.Current.Server.MapPath("") + 
    "''XMLSchema''" + 
    "ABC.xml");
XMLNodesList nodes1 = objXmlDocument1.GetElementsByTagName("Designation");
foreach (XmlNode n in nodes1) {
    if (n.Attributes["Role"].Value.Trim().Equals("XXX"){                                
        objnode1 = n;
        break;
    }
}
if (objnode1 != null){
    XmlNodeList innerNodes1 = objnode1.ChildNodes;
    XmlNode newNode1 = objXmlDocument1.CreateElement("Designation");
    XmlAttribute newAtt1 = objXmlDocument1.CreateAttribute("Role");
    newAtt1.Value = "Ka";
    newNode1.Attributes.Append(newAtt1);
    newNode1.InnerXml=objnode1.InnerXml;
    objXmlDocument1.DocumentElement.AppendChild(newNode1);
}
objXmlDocument1.Save(
    System.Web.HttpContext.Current.Server.MapPath("") + 
    "''XMLSchema''" + 
    "ABC.xml");