简体   繁体   English

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

[英]How to copy a structure of nodes from one xml to an other with a different namespace?

I have two XML files with two different XSD schemas and different namespaces. 我有两个具有两个不同的XSD架构和不同的名称空间的XML文件。 They have both an identical substructure. 它们具有相同的子结构。 And now i need to copy that node (and all childs) from one XML document to the other one. 现在,我需要将该节点(和所有子节点)从一个XML文档复制到另一个XML文档。

Clone would do, if the namespaces were the same. 如果名称空间相同,则将执行克隆操作。 Is there a nice way to do it? 有一个不错的方法吗? (The substructure will change later on - but will be kept identical.) (子结构稍后会更改-但将保持不变。)

Basically, you need an XSL transformation that creates new elements with equal names, but a different namespace. 基本上,您需要一个XSL转换来创建名称相同但名称空间不同的新元素。

Consider the following input XML: 考虑以下输入XML:

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

Now you need a template that says "copy structure and name of everything you see, but declare a new namespace while you're at it": 现在,您需要一个模板,上面写着“复制所见内容的结构和名称,但在使用时声明一个新的名称空间”:

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

When you run the above XML through it, this produces: 当您通过它运行上述XML时,将产生:

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

All your http://tempuri.org/ns_old elements have effectively changed their namespace. 您所有的http://tempuri.org/ns_old元素都有效地更改了其命名空间。 When your input XML has more than one namespace at the same time, the XSL must most likely be extended a bit. 当您的输入XML同时具有多个名称空间时,很有可能必须扩展XSL。

In case you wish to copy all the sub elements of a node on matching of some attribute. 如果您希望在匹配某个属性时复制节点的所有子元素。 You can just copy the InnerXML of referenced node and set it equal to new node. 您可以只复制引用节点的InnerXML并将其设置为等于新节点。

Something like this, below, I have a XML block with Document Element or Root element as Tablist , I need to add new node under Tablist with Role="Ka" and all the sub nodes of Ka should be same as XXX: 像这样的事情,下面,我有一个文档元素元素作为一个XML块Tablist ,我需要在添加新节点TablistRole="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>

So I just write following code: 所以我只写下面的代码:

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");

Not sure if this applies, but I've done something similar working with two xml docs in vb.net: 不知道这是否适用,但是我对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

Following Tomalak's example(with a little fix), but use SetAttribute + OuterXml + InnerXml is much more simple const string xml_str = @" 遵循Tomalak的示例(有一点点修复),但是使用SetAttribute + OuterXml + InnerXml更加简单,const字符串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 );

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM