2008-10-30 7 views
1

J'ai deux fichiers XML avec deux schémas XSD différents et des espaces de noms différents. Ils ont tous les deux une sous-structure identique. Et maintenant j'ai besoin de copier ce nœud (et tous les enfants) d'un document XML à l'autre.Comment copier une structure de nœuds d'un xml à un autre avec un espace de noms différent?

Le clonage ferait l'affaire, si les espaces de noms étaient les mêmes. Y a-t-il une bonne façon de le faire? (La sous-structure changera plus tard, mais restera identique.)

Répondre

3

Fondamentalement, vous avez besoin d'une transformation XSL qui crée de nouveaux éléments avec des noms égaux, mais un espace de noms différent.

Tenir compte XML d'entrée suivante:

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

Maintenant, vous avez besoin d'un modèle qui dit « structure de copie et nom de tout ce que vous voyez, mais déclarer un nouvel espace de noms pendant que vous y êtes »:

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

Lorsque vous exécutez le code XML ci-dessus à travers elle, ce produit:

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

Toutes vos http://tempuri.org/ns_old éléments ont effectivement changé leur espace de noms. Lorsque votre XML d'entrée a plus d'un espace de noms en même temps, le XSL doit très probablement être étendu un peu.

0

Je ne sais pas si cela vaut, mais je l'ai fait quelque chose de similaire travaillant avec deux documents XML dans 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 
0

Suivant l'exemple de Tomalak (avec un peu de difficulté), mais utilisez SetAttribute + OuterXml + InnerXml est beaucoup plus simple chaîne 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); 

}

0

Si vous souhaitez copier tous les éléments sous d'un noeud sur la correspondance d'un attribut. Vous pouvez simplement copier le InnerXML du noeud référencé et le définir comme égal au nouveau noeud.

Quelque chose comme ça, ci-dessous, j'ai un bloc XML avec Element document ou élément racine comme Tablist, je dois d'ajouter un nouveau nœud sous Tablist avec Role="Ka" et tous les sous-nœuds de Ka devraient être les mêmes que 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> 

Je viens d'écrire le code suivant:

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