it-swarm.dev

Jak se vypořádat s XML v jazyce C #

Jaký je nejlepší způsob, jak se vypořádat s dokumenty XML, XSD atd. V C # 2.0? 

Které třídy použít atd. Jaké jsou nejlepší postupy analýzy a tvorby dokumentů XML atd. 

EDIT:. Net 3.5 návrhy jsou také vítány.

79

Primární způsob čtení a zápisu do C # 2.0 se provádí pomocí třídy XmlDocument. Většinu nastavení můžete načíst přímo do XmlDocument prostřednictvím XmlReader, který přijímá.

Načítání XML přímo

XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");

Načítání XML ze souboru

XmlDocument document = new XmlDocument();
document.Load(@"C:\Path\To\xmldoc.xml");
// Or using an XmlReader/XmlTextReader
XmlReader reader = XmlReader.Create(@"C:\Path\To\xmldoc.xml");
document.Load(reader);

Nejjednodušší/nejrychlejší způsob, jak číst dokument XML, je pomocí XPath.

Čtení XML dokumentu pomocí XPath (pomocí XmlDocument, který nám umožňuje editovat)

XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");

// Select a single node
XmlNode node = document.SelectSingleNode("/People/Person[@Name = 'Nick']");

// Select a list of nodes
XmlNodeList nodes = document.SelectNodes("/People/Person");

Pokud potřebujete pracovat s dokumenty XSD pro ověření dokumentu XML, můžete jej použít.

Ověření dokumentů XML proti schématům XSD

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidateType = ValidationType.Schema;
settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd

XmlReader reader = XmlReader.Create(pathToXml, settings);
XmlDocument document = new XmlDocument();

try {
    document.Load(reader);
} catch (XmlSchemaValidationException ex) { Trace.WriteLine(ex.Message); }

Ověření XML proti XSD v každém uzlu (UPDATE 1)

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidateType = ValidationType.Schema;
settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd
settings.ValidationEventHandler += new ValidationEventHandler(settings_ValidationEventHandler);

XmlReader reader = XmlReader.Create(pathToXml, settings);
while (reader.Read()) { }

private void settings_ValidationEventHandler(object sender, ValidationEventArgs args)
{
    // e.Message, e.Severity (warning, error), e.Error
    // or you can access the reader if you have access to it
    // reader.LineNumber, reader.LinePosition.. etc
}

Psaní dokumentu XML (ručně)

XmlWriter writer = XmlWriter.Create(pathToOutput);
writer.WriteStartDocument();
writer.WriteStartElement("People");

writer.WriteStartElement("Person");
writer.WriteAttributeString("Name", "Nick");
writer.WriteEndElement();

writer.WriteStartElement("Person");
writer.WriteStartAttribute("Name");
writer.WriteValue("Nick");
writer.WriteEndAttribute();
writer.WriteEndElement();

writer.WriteEndElement();
writer.WriteEndDocument();

writer.Flush();

(UPDATE 1)

V .NET 3.5 můžete použít XDocument k provádění podobných úkolů. Rozdíl je však v tom, že máte výhodu v provádění dotazů Linq pro výběr přesných dat, která potřebujete. S přidáním inicializátorů objektů můžete vytvořit dotaz, který dokonce vrátí objekty vlastní definice přímo do dotazu.

    XDocument doc = XDocument.Load(pathToXml);
    List<Person> people = (from xnode in doc.Element("People").Elements("Person")
                       select new Person
                       {
                           Name = xnode.Attribute("Name").Value
                       }).ToList();

(UPDATE 2)

Pěkným způsobem v .NET 3.5 je použít XDocument k vytvoření XML je níže. Tím se kód zobrazí v podobném vzoru jako požadovaný výstup.

XDocument doc =
        new XDocument(
              new XDeclaration("1.0", Encoding.UTF8.HeaderName, String.Empty),
              new XComment("Xml Document"),
              new XElement("catalog",
                    new XElement("book", new XAttribute("id", "bk001"),
                          new XElement("title", "Book Title")
                    )
              )
        );

vytvoří 

<!--Xml Document-->
<catalog>
  <book id="bk001">
    <title>Book Title</title>
  </book>
</catalog>

Vše ostatní se nezdaří, můžete si přečíst tento článek MSDN, který obsahuje mnoho příkladů, o kterých jsem zde diskutoval a další. http://msdn.Microsoft.com/en-us/library/aa468556.aspx

167
nyxtom

Záleží na velikosti; pro malé až střední velikosti xml, DOM jako XmlDocument (všechny verze C # /. NET) nebo XDocument (.NET 3.5/C # 3.0) je zřejmým vítězem. Pro použití xsd, můžete načíst xml pomocí XmlReader , a XmlReader přijme (do Vytvořit ) a XmlReaderSettings . Objekty XmlReaderSettings mají vlastnost Schemas , která může být použita k provedení ověření xsd (nebo dtd).

Pro psaní XML platí stejné věci, s tím, že je jednodušší rozložit obsah pomocí LINQ-to-XML (XDocument) než starší XmlDocument.

Nicméně, pro obrovské xml, DOM může chomp příliš mnoho paměti, v takovém případě budete muset použít XmlReader/XmlWriter přímo.

Nakonec, pro manipulaci s XML můžete použít XslCompiledTransform (vrstva xslt).

Alternativou k práci s xml je práce s objektovým modelem; můžete použít xsd.exe k vytvoření tříd, které představují model kompatibilní s xsd, a jednoduše načíst xml as objekty, manipulovat s nimi s OO a pak tyto objekty znovu serializovat; to uděláte s XmlSerializer .

29
Marc Gravell

odpověď nyxtomu je velmi dobrá. Přidám pár věcí:

Pokud potřebujete přístup k dokumentu XML pouze pro čtení, XPathDocument je objekt s mnohem menší hmotností než objekt XmlDocument

Nevýhodou použití XPathDocument je, že nemůžete použít známé SelectNodes a SelectSingleNode metody XmlNode. Místo toho musíte použít nástroje, které soubor IXPathNavigable poskytuje: použijte CreateNavigator k vytvoření XPathNavigator a použijte XPathNavigator k vytvoření XPathNodeIterators k iteraci přes seznamy uzlů, které najdete přes XPath. To obvykle vyžaduje několik dalších řádků kódu než metody XmlDocument.

Ale: XmlDocument a XmlNode třídy implementují IXPathNavigable, takže jakýkoliv kód, který píšete pro použití těchto metod na XPathDocument, bude také pracovat na XmlDocument. Pokud si zvyknete na psaní proti IXPathNavigable, vaše metody mohou pracovat proti oběma objektům. (To je důvod, proč je použití XmlNode a XmlDocument v signaturách metody označeno FxCop.)

XDocument a XElement (a XNode a XObject) nezavádějí IXPathNavigable.

Další věc, která v nyxtomově odpovědi není, je XmlReader. Obecně používáte XmlReader, abyste se vyhnuli režii analýzy datového toku XML do objektového modelu před jeho zpracováním. Místo toho použijete XmlReader ke zpracování vstupního toku jednoho uzlu XML najednou. To je v podstatě odpověď .NET na SAX. To vám umožní napsat velmi rychlý kód pro zpracování velmi velkých XML dokumentů. 

XmlReader také poskytuje nejjednodušší způsob zpracování fragmentů dokumentů XML, např. tok XML elementů bez vloženého elementu, který vrací SQL Server FOR XML RAW.

Kód, který píšete pomocí XmlReader, je obecně velmi úzce spojený s formátem XML, který čte. Použití XPath umožňuje, aby váš kód byl hodně, mnohem více spojený s XML, což je důvod, proč je to obecně správná odpověď. Ale když potřebujete použít XmlReader, opravdu to potřebujete.

12
Robert Rossney

101 Vzorky Linq 

http://msdn.Microsoft.com/en-us/library/bb387098.aspx

a ukázky Linq na XML

http://msdn.Microsoft.com/en-us/vbasic/bb688087.aspx

A myslím, že Linq usnadňuje XML.

4
emremp

Nejprve se seznamte s novými třídami XDocument a XElement, protože se jedná o zlepšení oproti předchozí rodině XmlDocument. 

  1. Pracují s LINQ 
  2. Jsou rychlejší a lehčí

Nicméně, budete muset stále používat staré třídy pro práci s kódem starší - zejména dříve generované proxy. V takovém případě se budete muset seznámit s některými vzory pro spolupráci mezi těmito třídami zpracování XML.

Domnívám se, že vaše otázka je poměrně široká a vyžadovala by příliš mnoho informací v jediné odpovědi, ale toto je první obecná odpověď, na kterou jsem myslel, a slouží jako začátek.

4
hurst

Pokud pracujete v .NET 3.5 a nejste zkuseni experimentálního kódu, můžete se podívat na LINQ to XSD ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq- to-xsd-alpha-0-2.aspx ), která bude generovat .NET třídy z XSD (včetně vestavěných pravidel z XSD).

To pak má schopnost psát přímo ven k souboru a číst ze souboru zajistit, že to odpovídá pravidlům XSD.

Rozhodně doporučuji mít XSD pro jakýkoli XML dokument, se kterým pracujete:

  • Umožňuje vynutit pravidla v XML
  • Umožňuje ostatním, aby viděli, jak je/bude struktura XML strukturována
  • Lze použít pro validaci XML

Zjistil jsem, že Liquid XML Studio je skvělý nástroj pro generování XSD a je to zdarma!

2
Aaron Powell

Můj osobní názor, jako programátor C #, je, že nejlepším způsobem, jak se vypořádat s XML v jazyce C #, je delegovat tuto část kódu na projekt VB .NET. V .NET 3.5, VB .NET je XML literatura, která dělá jednání s XML mnohem intuitivnějším. Viz například:

Přehled LINQ XML v jazyce Visual Basic

(Nezapomeňte nastavit stránku tak, aby zobrazovala kód VB, nikoli kód C #.)

Zbytek projektu bych napsal v C #, ale zpracovávám XML v odkazovaném projektu VB.

1
Ryan Lundy

Zápis XML s třídou XmlDocument 

//itemValues is collection of items in Key value pair format
//fileName i name of XML file which to creatd or modified with content
    private void WriteInXMLFile(System.Collections.Generic.Dictionary<string, object> itemValues, string fileName)
    {
        string filePath = "C:\\\\tempXML\\" + fileName + ".xml";
        try
        {

            if (System.IO.File.Exists(filePath))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);                   

                XmlNode rootNode = doc.SelectSingleNode("Documents");

                XmlNode pageNode = doc.CreateElement("Document");
                rootNode.AppendChild(pageNode);


                foreach (string key in itemValues.Keys)
                {

                    XmlNode attrNode = doc.CreateElement(key);
                    attrNode.InnerText = Convert.ToString(itemValues[key]);
                    pageNode.AppendChild(attrNode);
                    //doc.DocumentElement.AppendChild(attrNode);

                }
                doc.DocumentElement.AppendChild(pageNode);
                doc.Save(filePath);
            }
            else
            {
                XmlDocument doc = new XmlDocument();
                using(System.IO.FileStream fs = System.IO.File.Create(filePath))
                {
                    //Do nothing
                }

                XmlNode rootNode = doc.CreateElement("Documents");
                doc.AppendChild(rootNode);
                doc.Save(filePath);

                doc.Load(filePath);

                XmlNode pageNode = doc.CreateElement("Document");
                rootNode.AppendChild(pageNode);

                foreach (string key in itemValues.Keys)
                {                          
                    XmlNode attrNode = doc.CreateElement(key);                           
                    attrNode.InnerText = Convert.ToString(itemValues[key]);
                    pageNode.AppendChild(attrNode);
                    //doc.DocumentElement.AppendChild(attrNode);

                }
                doc.DocumentElement.AppendChild(pageNode);

                doc.Save(filePath);

            }
        }
        catch (Exception ex)
        {

        }

    }

OutPut look like below
<Dcouments>
    <Document>
        <DocID>01<DocID>
        <PageName>121<PageName>
        <Author>Mr. ABC<Author>
    <Dcoument>
    <Document>
        <DocID>02<DocID>
        <PageName>122<PageName>
        <Author>Mr. PQR<Author>
    <Dcoument>
</Dcouments>
1
Anil Rathod

Pokud v návrháři vytvoříte typovou datovou množinu, pak automaticky získáte objekt xsd, silně typovaný objekt a můžete načíst a uložit XML s jedním řádkem kódu.

1
Peter C

Pokud potřebujete data převést mezi XmlNode <=> XNode <=> XElement
(např. pro použití LINQ) vám toto rozšíření může pomoci:

public static class MyExtensions
{
    public static XNode GetXNode(this XmlNode node)
    {
        return GetXElement(node);
    }

    public static XElement GetXElement(this XmlNode node)
    {
        XDocument xDoc = new XDocument();
        using (XmlWriter xmlWriter = xDoc.CreateWriter())
            node.WriteTo(xmlWriter);
        return xDoc.Root;
    }

    public static XmlNode GetXmlNode(this XElement element)
    {
        using (XmlReader xmlReader = element.CreateReader())
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlReader);
            return xmlDoc;
        }
    }

    public static XmlNode GetXmlNode(this XNode node)
    {
        return GetXmlNode(node);
    }
}

Používání:

XmlDocument MyXmlDocument = new XmlDocument();
MyXmlDocument.Load("MyXml.xml");
XElement MyXElement = MyXmlDocument.GetXElement(); // Convert XmlNode to XElement
List<XElement> List = MyXElement.Document
   .Descendants()
   .ToList(); // Now you can use LINQ
...
0
Michael Hutter

Cookeyho odpověď je dobrá ... ale zde jsou podrobné instrukce, jak vytvořit objekt s výrazným typem z XSD (nebo XML) a serializovat/deserializovat v několika řádcích kódu:

Pokyny

0
Steve Horn

nyxtom,

Neměli by "doc" a "xdoc" odpovídat v příkladu 1?

XDocument **doc** = XDocument.Load(pathToXml);
List<Person> people = (from xnode in **xdoc**.Element("People").Elements("Person")
                   select new Person
                   {
                       Name = xnode.Attribute("Name").Value
                   }).ToList();
0
mokumaxCraig