Как бороться с XML в C # - PullRequest
80 голосов
/ 21 октября 2008

Как лучше всего обращаться с XML-документами, XSD и т. Д. В C # 2.0?

Какие классы использовать и т. Д. Каковы лучшие методы анализа и создания документов XML и т. Д.

РЕДАКТИРОВАТЬ: .Net 3.5 предложения также приветствуются.

Ответы [ 12 ]

170 голосов
/ 21 октября 2008

Основным средством чтения и записи в C # 2.0 является класс XmlDocument . Вы можете загрузить большинство своих настроек непосредственно в XmlDocument через XmlReader, который он принимает.

Загрузка XML напрямую

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

Загрузка XML из файла

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

Я считаю, что самый простой / быстрый способ чтения XML-документа - использовать XPath.

Чтение XML-документа с использованием XPath (с использованием XmlDocument, который позволяет нам редактировать)

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

Если вам нужно работать с документами XSD для проверки XML-документа, вы можете использовать это.

Проверка документов XML по схемам 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); }

Проверка XML по XSD на каждом узле (ОБНОВЛЕНИЕ 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-документа (вручную)

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

(ОБНОВЛЕНИЕ 1)

В .NET 3.5 вы используете XDocument для выполнения аналогичных задач. Разница, однако, в том, что у вас есть преимущество выполнения запросов Linq для выбора точных данных, которые вам нужны. С добавлением инициализаторов объектов вы можете создать запрос, который даже возвращает объекты вашего собственного определения прямо в самом запросе.

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

(ОБНОВЛЕНИЕ 2)

Хороший способ в .NET 3.5 - использовать XDocument для создания XML ниже. Это приводит к тому, что код выглядит аналогично желаемому результату.

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

создает

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

Все остальное терпит неудачу, вы можете проверить эту статью MSDN, в которой есть много примеров, которые я обсуждал здесь и многое другое. http://msdn.microsoft.com/en-us/library/aa468556.aspx

29 голосов
/ 21 октября 2008

зависит от размера; для малого и среднего размера XML DOM, такой как XmlDocument (любые версии C # /. NET) или XDocument (.NET 3.5 / C # 3.0), является очевидным победителем. Для использования xsd Вы можете загрузить xml, используя XmlReader , и XmlReader принимает (до Создать ) XmlReaderSettings . Объекты XmlReaderSettings имеют свойство Schemas , которое можно использовать для проверки xsd (или dtd).

Для написания XML применимы те же действия, отметив, что разметить содержимое с помощью LINQ-to-XML (XDocument) немного проще, чем более старый XmlDocument.

Однако для огромного xml DOM может сжать слишком много памяти, и в этом случае вам может понадобиться использовать XmlReader / XmlWriter напрямую.

Наконец, для управления xml вы можете использовать XslCompiledTransform (слой xslt).

Альтернативой работе с xml является работа с объектной моделью; вы можете использовать xsd.exe для создания классов, представляющих xsd-совместимую модель, и просто загрузить xml как объекты , манипулировать им с помощью OO, а затем снова сериализовать эти объекты; Вы делаете это с XmlSerializer .

12 голосов
/ 21 октября 2008

Nyxtom ответ очень хороший. Я бы добавил к этому пару вещей:

Если вам нужен доступ только для чтения к XML-документу, XPathDocument гораздо легче, чем XmlDocument.

Недостатком использования XPathDocument является то, что вы не можете использовать знакомые SelectNodes и SelectSingleNode методы XmlNode. Вместо этого вы должны использовать инструменты, предоставляемые IXPathNavigable: используйте CreateNavigator, чтобы создать XPathNavigator, и используйте XPathNavigator, чтобы создать XPathNodeIterator s, чтобы перебирать списки узлов, которые вы найдете через XPath. Обычно для этого требуется несколько строк кода, чем методы XmlDocument.

Но: классы XmlDocument и XmlNode реализуют IXPathNavigable, поэтому любой код, который вы пишете для использования этих методов на XPathDocument, также будет работать на XmlDocument. Если вы привыкли писать против IXPathNavigable, ваши методы могут работать против любого объекта. (Вот почему использование XmlNode и XmlDocument в сигнатурах методов помечается FxCop.)

К сожалению, XDocument и XElementXNode и XObject) не реализуют IXPathNavigable.

Еще одна вещь, которой нет в ответе nyxtom, это XmlReader. Как правило, вы используете XmlReader, чтобы избежать затрат на синтаксический анализ потока XML в объектную модель, прежде чем приступить к его обработке. Вместо этого вы используете XmlReader для обработки входного потока по одному узлу XML за раз. По сути, это ответ .NET на SAX. Это позволяет вам писать очень быстрый код для обработки очень больших XML-документов.

XmlReader также предоставляет самый простой способ обработки фрагментов XML-документов, например, поток элементов XML без включающего элемента, который возвращает опция SQL Server FOR XML RAW.

Код, который вы пишете с использованием XmlReader, как правило, очень тесно связан с форматом XML, который он читает. Использование XPath позволяет вашему коду гораздо, гораздо более слабо соединяться с XML, поэтому, как правило, это правильный ответ. Но когда вам нужно использовать XmlReader, вам это действительно нужно.

4 голосов
/ 21 октября 2008

Прежде всего, познакомьтесь с новыми классами XDocument и XElement , поскольку они являются улучшением по сравнению с предыдущим семейством XmlDocument.

  1. Они работают с LINQ
  2. Они быстрее и легче

Однако вам, возможно, придется по-прежнему использовать старые классы для работы с унаследованным кодом - особенно сгенерированными ранее прокси. В этом случае вам необходимо ознакомиться с некоторыми шаблонами взаимодействия между этими классами обработки XML.

Я думаю, что ваш вопрос довольно широк и потребует слишком много в одном ответе, чтобы дать подробности, но это первый общий ответ, о котором я подумал, и он служит началом.

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

101 образцов Linq

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

и Образцы Linq to XML

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

И я думаю, что Linq упрощает XML.

2 голосов
/ 21 октября 2008

Если вы работаете в .NET 3.5 и не боитесь экспериментального кода, вы можете проверить LINQ to XSD (http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to-xsd-alpha-0-2.aspx), который будет генерировать классы .NET из XSD (включая встроенные правила из XSD).

Затем он может записывать данные в файл и читать из файла, гарантируя, что он соответствует правилам XSD.

Я определенно предлагаю иметь XSD для любого XML-документа, с которым вы работаете:

  • Позволяет применять правила в XML
  • Позволяет другим увидеть, как XML будет / будет структурирован
  • Может использоваться для проверки XML

Я считаю, что Liquid XML Studio - отличный инструмент для создания XSD, и он бесплатный!

1 голос
/ 09 февраля 2016

Написание XML с классом 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 голос
/ 31 марта 2010

Мое личное мнение программиста на C # заключается в том, что лучший способ иметь дело с XML в C # - это делегировать эту часть кода в проект VB .NET. В .NET 3.5 VB .NET имеет литералы XML, которые делают работу с XML гораздо более интуитивно понятной. Смотрите здесь, например:

Обзор LINQ to XML в Visual Basic

(Убедитесь, что на странице отображается код VB, а не код C #.)

Я написал бы остальную часть проекта на C #, но обработал бы XML в ссылочном проекте VB.

1 голос
/ 21 октября 2008

Если вы создаете типизированный набор данных в конструкторе, то вы автоматически получаете xsd, строго типизированный объект, и можете загружать и сохранять xml одной строкой кода.

0 голосов
/ 28 августа 2018

Если вам когда-либо понадобится преобразовать данные между XmlNode <=> XNode <=> XElement
(например, чтобы использовать LINQ) это расширение может быть полезным для вас:

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

Использование:

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