C # 'da XML ile nasıl başa çıkılır


87

C # 2.0'da XML belgeleri, XSD vb. İle başa çıkmanın en iyi yolu nedir?

Hangi sınıfların kullanılacağı vb. XML belgelerini ayrıştırmanın ve oluşturmanın en iyi uygulamaları nelerdir?

DÜZENLEME: .Net 3.5 önerileri de açığız.


1
Daha uygulanabilir bir çözüm bulmaya çalışanlar için bunu görmezden gelin. Eski bir .NET kitaplığı. Bunun yerine XDocument kullanın ve hayal kırıklığıyla gözlerinizi
AER

Yanıtlar:


180

C # 2.0'da birincil okuma ve yazma yöntemi, XmlDocument sınıfı aracılığıyla yapılır . Ayarlarınızın çoğunu, kabul ettiği XmlReader aracılığıyla doğrudan XmlDocument'e yükleyebilirsiniz.

Doğrudan XML Yükleme

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

Dosyadan XML Yükleme

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

Bir XML belgesini okumanın en kolay / en hızlı yolunu XPath kullanmaktır.

XPath kullanarak bir XML Belgesini okumak (düzenlememize izin veren XmlDocument kullanarak)

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

Bir XML belgesini doğrulamak için XSD belgeleriyle çalışmanız gerekiyorsa, bunu kullanabilirsiniz.

XML Belgelerini XSD Şemalarına Göre Doğrulama

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

XML'yi her Düğümde XSD'ye karşı doğrulama (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
}

XML Belgesi Yazma (manuel olarak)

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

(GÜNCELLEME 1)

.NET 3.5'te, benzer görevleri gerçekleştirmek için XDocument kullanırsınız. Ancak fark, ihtiyacınız olan kesin verileri seçmek için Linq Sorguları gerçekleştirme avantajına sahip olmanızdır. Nesne başlatıcıların eklenmesiyle, kendi tanımınıza ait nesneleri doğrudan sorgunun içinde döndüren bir sorgu oluşturabilirsiniz.

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

(GÜNCELLEME 2)

NET 3.5'te XML oluşturmak için XDocument'ı kullanmanın güzel bir yolu aşağıdadır. Bu, kodun istenen çıktıya benzer bir modelde görünmesini sağlar.

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

oluşturur

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

Her şey başarısız olursa, burada tartıştığım birçok örneği ve daha fazlasını içeren bu MSDN makalesine göz atabilirsiniz. http://msdn.microsoft.com/en-us/library/aa468556.aspx


3
Son örnekte XDocument'ı kullandığınızı belirtmek isteyebilirsiniz çünkü XDocument, XmlDocument'ten oldukça farklıdır
Aaron Powell

2
Düzeltme; C # 3.5 yoktur; .NET 3.5 ve C # 3.0
Marc Gravell

oh, ve "anında" [nesne başlatıcıları] C # 3.0 ve XmlDocument ile büyük ölçüde aynı şekilde çalışacaktı - yine de iyi bir yanıt, yine de (+1)
Marc Gravell

XPath ile sorgulamak için bir belge yüklüyorsanız (ve düzenlemek için değil), o zaman bir XPathDocument kullanmanın çok daha verimli olacağını belirtmekte fayda var
Oliver Hallam

Bu Şema Doğrulaması düğümlere göre mi yapılıyor? Değilse, bunu düğüm düğüm yapmanın bir yolu var mı?
Malik Daud Ahmad Khokhar

30

Boyuta bağlıdır; küçük ila orta boyutlu xml için, XmlDocument (herhangi bir C # /. NET sürümleri) veya XDocument (.NET 3.5 / C # 3.0) gibi bir DOM bariz bir şekilde kazanır. Xsd kullanmak için, Sen xml bir kullanarak yükleyebilirsiniz XmlReader ve bir XmlReader (için kabul eder oluşturun bir) XmlReaderSettings . XmlReaderSettings nesneleri, xsd (veya dtd) doğrulaması gerçekleştirmek için kullanılabilen bir Schemas özelliğine sahiptir.

Xml yazmak için, LINQ-to-XML (XDocument) ile içerik düzenlemenin eski XmlDocument'e göre biraz daha kolay olduğunu belirterek, aynı şeyler geçerlidir.

Ancak, büyük xml için bir DOM çok fazla belleği parçalayabilir, bu durumda doğrudan XmlReader / XmlWriter kullanmanız gerekebilir.

Son olarak, xml'yi işlemek için XslCompiledTransform'u (bir xslt katmanı) kullanmak isteyebilirsiniz .

Xml ile çalışmanın alternatifi, bir nesne modeliyle çalışmaktır; xsd.exe'yi , xsd uyumlu bir modeli temsil eden sınıflar oluşturmak için kullanabilir ve xml'yi nesneler olarak yükleyebilir, OO ile işleyebilir ve sonra bu nesneleri yeniden serileştirebilirsiniz; bunu XmlSerializer ile yaparsınız .


Büyük bir XML belgesini (40k satır) işlemek (öğeleri eklemek / desteklemek). En iyi yol nedir? LINQ-to-XML kullanıyordum.
Neyoh

12

nyxtom'un cevabı çok güzel. Ona birkaç şey eklerim:

Bir XML belgesine salt okunur erişime ihtiyacınız varsa XPathDocument, bu çok daha hafif bir nesnedir XmlDocument.

Kullanmanın dezavantajı XPathDocument, tanıdık SelectNodesve SelectSingleNodeyöntemlerini kullanamamanızdır XmlNode. Bunun yerine, aşağıdakilerin IXPathNavigablesağladığı araçları kullanmanız CreateNavigatorgerekir: bir oluşturmak için XPathNavigatorkullanın ve XPath aracılığıyla bulduğunuz düğüm listeleri üzerinde yineleme XPathNavigatoryapmak için XPathNodeIterators oluşturmak için kullanın . Bu genellikle XmlDocumentyöntemlerden birkaç satır daha fazla kod gerektirir .

Ancak: XmlDocumentve XmlNodesınıfları uygulanır IXPathNavigable, bu nedenle bu yöntemleri kullanmak için yazdığınız herhangi bir kod XPathDocument, bir XmlDocument. Karşı yazmaya alışırsanız IXPathNavigable, yöntemleriniz her iki nesneye karşı da çalışabilir. ( Yöntem imzalarının kullanılması XmlNodeve kullanılmasının XmlDocumentFxCop tarafından işaretlenmesinin nedeni budur .)

Ne yazık, XDocumentve XElement(ve XNodeve XObject) uygulamak gerekmez IXPathNavigable.

Nyxtom'un cevabında bulunmayan başka bir şey de XmlReader. Genellikle XmlReaderXML akışını işlemeye başlamadan önce bir nesne modeline ayrıştırmanın ek yükünden kaçınmak için kullanırsınız . Bunun yerine, XmlReadergiriş akışını her seferinde bir XML düğümü işlemek için bir kullanırsınız . Bu esasen .NET'in SAX'e cevabıdır. Çok büyük XML belgelerini işlemek için çok hızlı kod yazmanıza olanak tanır.

XmlReader ayrıca XML belge parçalarını işlemenin en basit yolunu sağlar, örneğin, SQL Server'ın FOR XML RAW seçeneğinin döndürdüğü kapsayıcı öğe olmadan XML öğelerinin akışı.

Kullanarak yazdığınız kod XmlReader, genellikle okuduğu XML formatına çok sıkı bir şekilde bağlıdır. XPath kullanmak, kodunuzun XML ile çok daha gevşek bir şekilde eşleşmesine izin verir, bu yüzden genellikle doğru cevaptır. Ancak kullanmanız gerektiğinde XmlReader, gerçekten buna ihtiyacınız var.


3
XPathNavigator CreateNavigator(this XNode node)Bir XPathNavigatorden XNode(türetilmiş sınıfı içeren XDocument) oluşturmak için bir uzantı yöntemi olduğunu unutmayın .
Dave

5

Her şeyden önce, yeni XDocument ve XElement sınıflarını tanıyın , çünkü bunlar önceki XmlDocument ailesine göre bir gelişme.

  1. LINQ ile çalışıyorlar
  2. Daha hızlı ve daha hafiftirler

Ancak , eski kodla, özellikle önceden oluşturulmuş proxy'lerle çalışmak için yine de eski sınıfları kullanmanız gerekebilir. Bu durumda, bu XML işleme sınıfları arasında birlikte çalışmak için bazı kalıplara aşina olmanız gerekecektir.

Sorunuzun oldukça geniş olduğunu ve ayrıntı vermek için tek bir cevapta çok fazla şey gerektireceğini düşünüyorum, ancak bu aklıma gelen ilk genel cevap ve başlangıç ​​olarak hizmet ediyor.


Bunların (XDocument vb.) Harika olduğuna katılıyorum, ancak OP C # 2.0'ı sordu.
Marc Gravell


2

.NET 3.5'te çalışıyorsanız ve deneysel koddan çekinmiyorsanız, LINQ to XSD'ye göz atabilirsiniz ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to- xsd-alpha-0-2.aspx ) bir XSD'den .NET sınıfları oluşturacaktır ( XSD'deki yerleşik kurallar dahil).

Daha sonra, doğrudan bir dosyaya yazma ve bir dosyadan okuma, XSD kurallarına uyduğundan emin olma yeteneğine sahiptir.

Çalıştığınız herhangi bir XML belgesi için kesinlikle bir XSD'ye sahip olmanızı öneririm:

  • XML'deki kuralları uygulamanıza izin verir
  • Başkalarının XML'in nasıl yapılandırıldığını / yapılacağını görmelerine izin verir
  • XML doğrulaması için kullanılabilir

Liquid XML Studio'nun XSD'ler oluşturmak için harika bir araç olduğunu düşünüyorum ve ücretsiz!


2

XmlDocument sınıfıyla XML yazma

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

Tasarımcıda yazılı bir veri kümesi oluşturursanız, otomatik olarak bir xsd, güçlü yazılmış bir nesne alırsınız ve xml'yi bir satır kodla yükleyebilir ve kaydedebilirsiniz.


DataSet'ler ile büyük başarı elde ettim. Veritabanları konusunda da çok arkadaş canlısıdırlar.
Kullanıcı 1

1

Bir C # programcısı olarak benim kişisel fikrim, C # 'da XML ile başa çıkmanın en iyi yolunun, kodun bu bölümünü bir VB .NET projesine devretmek olduğudur. .NET 3.5'te, VB .NET, XML ile uğraşmayı çok daha sezgisel hale getiren XML Literals'e sahiptir. Örneğin buraya bakın:

Visual Basic'te LINQ to XML'e genel bakış

(Sayfayı C # kodunu değil, VB kodunu gösterecek şekilde ayarladığınızdan emin olun.)

Projenin geri kalanını C # ile yazardım, ancak başvurulan bir VB projesinde XML'i ele alırdım.


Sadece XML için değişmeye değmez. XML yalnızca değişmez değerlerle ilgilenir. Xml bir parametre olarak aktarılırsa, XML hazır bilgi desteği size pek bir fayda sağlamaz. Bunun yerine, vb.net'in eski sözdizimi, C #'ın mutlu programlama deneyimini mahvedecektir.
Gqqnbig

0

Nyxtom,

Örnek 1'deki "doc" ve "xdoc" eşleşmemeli mi?

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

Bahsettiğiniz yanıtın onaylanması için bir düzenleme gönderdim, ancak bu bir yanıt değil, gerçekten bir yorum olmalıydı.
David Thompson

Teşekkürler David. Anlaşıldı, o zaman yorum yapmama izin vermezdi. Emin değilim neden.
mokumaxCraig

0

Cookey'nin cevabı güzel ... ancak işte bir XSD'den (veya XML) güçlü bir şekilde yazılmış bir nesnenin nasıl oluşturulacağına ve birkaç satır kodda serileştirme / seriyi kaldırma hakkında ayrıntılı talimatlar:

Talimatlar


"Aradığınız sayfa mevcut değil." :(
Ian Grainger

0

Verileri XmlNode<=> XNode<=> arasında dönüştürmeniz gerekirse XElement
(örneğin, LINQ kullanmak için) bu Uzantılar sizin için yararlı olabilir:

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

Kullanım:

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
...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.