Avatar billede iluka Nybegynder
31. august 2004 - 13:57 Der er 13 kommentarer og
1 løsning

merge / sammensætte XML

Hej

Jeg har et par xml dokumenter (XmlDocument) som jeg gerne vil smelte sammen til 1.

Hvis f.eks. dokumenterne ser sådan her ud
<root>
  <menu>
    <menuitem id="1" />
  </menu>
</root

og
<root>
  <menu>
    <menuitem id="2" />
  </menu>
</root>

så vi jeg gerne have et dokument der ser sådan her ud:
<root>
  <menu>
    <menuitem id="1" />
    <menuitem id="2" />
  </menu>
</root>

Er der en smart måde at gøre det på med C#?

- Kasper
Avatar billede arne_v Ekspert
31. august 2004 - 14:24 #1
Ganske almindelig XML klasser må da kunne bruges:

lave nyt tomt XmlDocument
lave root og menu elements
åben alle filer og for hver
    load fil ind i XmlDocument
    læs alle menuitem tags for hver hver
        tilføj dem til nyt dokument
udskriv nye dokument til fil.
Avatar billede iluka Nybegynder
31. august 2004 - 14:30 #2
ok... how???
Avatar billede arne_v Ekspert
31. august 2004 - 14:35 #3
Lidt kode framenter:

using System.Xml;
...
XmlDocument newdoc = new XmlDocument();
XmlElement root = newdoc.CreateElement("root");
newdoc.AppendChild(root)
XmlElement menu = newdoc.CreateElement("menu");
root.AppendChild(menu)
...
  XmlDocument olddoc = new XmlDocument();
  olddoc.Load(filnavn);
  XmlNodeList elements = doc.GetElementsByTagName("menuitem");
  foreach(XmlNode element in elements)
  {
      XmlElement menuitem = newdoc.CreateElement("menuitem");
      menuitem.AppendChild(newdoc.CreateTextNode(element.FirstChild.Value));
      menuitem.SetAttribute("id", element.GetAttribute("id"));
      menu.AppendChild(menuitem)
  }
...
doc.Save("noget.xml");
Avatar billede arne_v Ekspert
31. august 2004 - 14:36 #4
Det er bare tastet ind så der er muligvis lidt taste fejl.
Avatar billede iluka Nybegynder
31. august 2004 - 15:03 #5
her antager du så en statisk struktur, hvor du ved at alle elementer hedder "menuitem" og at du kender dybten. Det er mig der ikke har udtrykt mig ordentligt. Der kan være op til 8 niveauer i dybden af xml dokumenterne, og jeg aner ikke hvad de enkelte elementer hedder (og dem er der typisk 100-1000 af). Den løsning du foreslår minder om hvad jeg selv kunne tænke på, men det jeg har brug for er noget mere dynamisk. Derfor havde jeg håbet på at der fandtes en metode der selv kan tage hvert element fra det ene dokument og sætte dem ind i det andet.
Avatar billede arne_v Ekspert
01. september 2004 - 13:25 #6
Du kan godt erstatte GetElementsByTagName og forech løkken med noget som
finder alt dynamisk.

Men normalt plejer XML at være lidt mere struktureret.
Avatar billede arne_v Ekspert
04. september 2004 - 11:10 #7
Struktuereret:

using System;
using System.Xml;

class MainClass
{
    public static void Main(string[] args)
    {
        string[] files = { @"C:\fil1.xml", @"C:\fil2.xml" };
        XmlDocument newdoc = new XmlDocument();
        XmlElement root = newdoc.CreateElement("root");
        newdoc.AppendChild(root);
        XmlElement menu = newdoc.CreateElement("menu");
        root.AppendChild(menu);
        for(int i = 0; i < files.Length; i++)
        {
            XmlDocument olddoc = new XmlDocument();
            olddoc.Load(files[i]);
            XmlNodeList elements = olddoc.GetElementsByTagName("menuitem");
            foreach(XmlNode element in elements)
            {
                XmlElement menuitem = newdoc.CreateElement("menuitem");
                menuitem.SetAttribute("id", ((XmlElement)element).GetAttribute("id"));
                menu.AppendChild(menuitem);
            }
        }
        newdoc.Save(@"C:\allfiles.xml");
    }
}

Ustruktuereret:

using System;
using System.Xml;

class MainClass
{
    private static void process(XmlNode oldnode, XmlNode newnode)
    {
        XmlNodeList childs = oldnode.ChildNodes;
        foreach(XmlNode child in childs)
        {
            switch(child.NodeType)
            {
                case XmlNodeType.Element:
                    XmlElement elm = newnode.OwnerDocument.CreateElement(child.Name);
                    foreach(XmlAttribute an in child.Attributes)
                    {
                        elm.SetAttribute(an.Name, an.Value);
                    }
                    newnode.AppendChild(elm);
                    process(child, elm);
                    break;
                case XmlNodeType.Attribute:
                    XmlAttribute attr = newnode.OwnerDocument.CreateAttribute(child.Name, child.Value);
                    newnode.AppendChild(attr);
                    break;
                case XmlNodeType.Text:
                    XmlText txt = newnode.OwnerDocument.CreateTextNode(child.Value);
                    newnode.AppendChild(txt);
                    break;
            }
        }
    }
    public static void Main(string[] args)
    {
        string[] files = { @"C:\fil1.xml", @"C:\fil2.xml" };
        XmlDocument newdoc = new XmlDocument();
        XmlElement root = newdoc.CreateElement("root");
        newdoc.AppendChild(root);
        for(int i = 0; i < files.Length; i++)
        {
            XmlDocument olddoc = new XmlDocument();
            olddoc.Load(files[i]);
            process(olddoc.DocumentElement, newdoc.DocumentElement);
        }
        newdoc.Save(@"C:\allfiles.xml");
        newdoc.Save(Console.Out);
    }
}
Avatar billede philox Nybegynder
06. september 2004 - 12:35 #8
Det kunne måske også være sjovt at se på metoden ImportNode
Avatar billede arne_v Ekspert
06. september 2004 - 12:48 #9
Ja faktisk - den ville spare en masse create.
Avatar billede philox Nybegynder
06. september 2004 - 13:12 #10
Man kan vel egentlig også bare snyde lidt:

[code]
string filenameImport1 = "my first xml";
string filenameImport2 = "my second xml";
string filenameMerged = "my merged file";

XmlTextReader xmlreader1 = new XmlTextReader(filenameImport1);
XmlTextReader xmlreader2 = new XmlTextReader(filenameImport2);

DataSet ds = new DataSet();
ds.ReadXml(xmlreader1);
DataSet ds2 = new DataSet();
ds2.ReadXml(xmlreader2);
ds.Merge(ds2);
ds.WriteXml(filenameMerged);
[/code]
Avatar billede philox Nybegynder
06. september 2004 - 13:14 #11
Men gælder jo kun for samme xml-struktur :-)
Avatar billede arne_v Ekspert
11. september 2004 - 21:12 #12
iluka>

Er du kommet videre ?
Avatar billede iluka Nybegynder
18. august 2010 - 13:53 #13
accepteret
Avatar billede arne_v Ekspert
18. august 2010 - 16:51 #14
du skal saette flueben og klikke accepter
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester