Как скопировать структуру узлов из одного XML в другой с другим пространством имен? - PullRequest
1 голос
/ 30 октября 2008

У меня есть два XML-файла с двумя разными схемами XSD и разными пространствами имен. Они имеют одинаковую подструктуру. И теперь мне нужно скопировать этот узел (и все дочерние элементы) из одного XML-документа в другой.

Клон сделал бы, если бы пространства имен были одинаковыми. Есть ли хороший способ сделать это? (Подструктура изменится позже - но останется идентичной.)

Ответы [ 4 ]

3 голосов
/ 30 октября 2008

По сути, вам необходимо преобразование 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, скорее всего, должен быть немного расширен.

0 голосов
/ 09 июля 2012

В случае, если вы хотите скопировать все вложенные элементы узла при сопоставлении какого-либо атрибута. Вы можете просто скопировать InnerXML указанного узла и установить его равным новому узлу.

Примерно так, ниже, у меня есть блок XML с Элементом документа или Корневой элемент как 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");
0 голосов
/ 10 февраля 2009

Следуя примеру Томалака (с небольшим исправлением), но использовать SetAttribute + OuterXml + InnerXml гораздо проще константная строка 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 );

}

0 голосов
/ 30 октября 2008

Не уверен, что это применимо, но я сделал нечто похожее, работая с двумя документами XML в vb.net:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...