Как лучше всего работать с XML-документами, XSD и т. Д. В C # 2.0?
Какие классы использовать и т. Д. Каковы лучшие практики синтаксического анализа и создания XML-документов и т. Д.
РЕДАКТИРОВАТЬ: предложения .Net 3.5 также приветствуются.
Как лучше всего работать с XML-документами, XSD и т. Д. В C # 2.0?
Какие классы использовать и т. Д. Каковы лучшие практики синтаксического анализа и создания XML-документов и т. Д.
РЕДАКТИРОВАТЬ: предложения .Net 3.5 также приветствуются.
Ответы:
Основные средства чтения и записи в C # 2.0 выполняются через класс XmlDocument . Вы можете загрузить большую часть своих настроек прямо в XmlDocument через XmlReader, который он принимает.
XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");
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.
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, вы можете использовать это.
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); }
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
}
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
Это зависит от размера; для XML- файлов малого и среднего размера очевидным победителем является DOM, например XmlDocument (любые версии C # /. NET) или XDocument (.NET 3.5 / C # 3.0). Для использования xsd вы можете загрузить xml с помощью XmlReader , и XmlReader принимает (для создания ) XmlReaderSettings . У объектов XmlReaderSettings есть схемы свойство которое можно использовать для выполнения проверки xsd (или dtd).
То же самое применимо и к написанию xml, но при этом следует отметить, что компоновка содержимого с помощью LINQ-to-XML (XDocument) немного проще, чем с помощью более старого XmlDocument.
Однако для огромного xml DOM может потреблять слишком много памяти, и в этом случае вам может потребоваться напрямую использовать XmlReader / XmlWriter.
Наконец, для управления xml вы можете использовать XslCompiledTransform (слой xslt).
Альтернативой работе с xml является работа с объектной моделью; вы можете использовать xsd.exe для создания классов, представляющих модель, совместимую с xsd, и просто загружать xml как объекты , манипулировать им с помощью объектно-ориентированного программирования, а затем снова сериализовать эти объекты; вы делаете это с помощью XmlSerializer .
Ответ nyxtom очень хорош. Я бы добавил к нему пару вещей:
Если вам нужен доступ только для чтения к XML-документу, XPathDocument
это гораздо более легкий объект, чемXmlDocument
.
Обратной стороной использования XPathDocument
является невозможность использования привычных SelectNodes
и привычных SelectSingleNode
методов XmlNode
. Вместо этого вы должны использовать инструменты, которые IXPathNavigable
предоставляет: используйте CreateNavigator
для создания XPathNavigator
и используйте XPathNavigator
to create XPathNodeIterator
s для перебора списков узлов, которые вы найдете с помощью XPath. Обычно для этого требуется на несколько строк кода больше, чемXmlDocument
методов.
Но: XmlDocument
и XmlNode
классы реализации IXPathNavigable
, поэтому любой код , вы пишете , чтобы использовать эти методы на XPathDocument
также будет работать над XmlDocument
. Если вы привыкнете писать против IXPathNavigable
, ваши методы могут работать против любого объекта. (Вот почему использование XmlNode
и XmlDocument
в сигнатурах методов отмечено FxCop.)
К сожалению, XDocument
и XElement
( XNode
и XObject
) не реализуют IXPathNavigable
.
Еще одна вещь, отсутствующая в ответе nyxtom, - это XmlReader
. Обычно вы используете, XmlReader
чтобы избежать накладных расходов на синтаксический анализ потока XML в объектную модель, прежде чем вы начнете его обрабатывать. Вместо этого вы используете XmlReader
для обработки входного потока по одному узлу XML за раз. По сути, это ответ .NET на SAX. Он позволяет писать очень быстрый код для обработки очень больших XML-документов.
XmlReader
также обеспечивает простейший способ обработки фрагментов XML-документа, например потока XML-элементов без включающего элемента, который возвращает опция FOR XML RAW SQL Server.
Код, который вы пишете, XmlReader
обычно очень тесно связан с форматом XML, который он читает. Использование XPath позволяет вашему коду быть намного, гораздо более слабым, связанным с XML, поэтому, как правило, это правильный ответ. Но когда нужно использовать XmlReader
, это действительно нужно.
XPathNavigator CreateNavigator(this XNode node)
для создания XPathNavigator
из XNode
(который включает производный класс XDocument
).
Прежде всего, познакомьтесь с новыми классами XDocument и XElement , поскольку они являются улучшением по сравнению с предыдущим семейством XmlDocument.
Однако вам, возможно, придется по-прежнему использовать старые классы для работы с устаревшим кодом, особенно с ранее созданными прокси. В этом случае вам нужно будет ознакомиться с некоторыми шаблонами взаимодействия между этими классами обработки XML.
Я думаю, что ваш вопрос довольно общий и потребует слишком многого в одном ответе, чтобы дать подробности, но это первый общий ответ, который я придумал, и он служит для начала.
101 образец Linq
http://msdn.microsoft.com/en-us/library/bb387098.aspx
и образцы Linq в XML
http://msdn.microsoft.com/en-us/vbasic/bb688087.aspx
И я думаю, что Linq упрощает XML.
Если вы работаете в .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-документа, с которым вы работаете:
Я считаю, что Liquid XML Studio - отличный инструмент для создания XSD, и он бесплатный!
Написание 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>
Мое личное мнение, как программиста на C #, заключается в том, что лучший способ работать с XML на C # - это делегировать эту часть кода проекту VB .NET. В .NET 3.5 в VB .NET есть XML-литералы, которые делают работу с XML более интуитивно понятной. См. Например:
Обзор LINQ to XML в Visual Basic
(Обязательно настройте страницу для отображения кода VB, а не кода C #.)
Я бы написал остальную часть проекта на C #, но обработал бы XML в проекте VB, на который имеется ссылка.
Никстом
Разве «doc» и «xdoc» не должны совпадать в примере 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();
Ответ Куки хорош ... но вот подробные инструкции о том, как создать строго типизированный объект из XSD (или XML) и сериализовать / десериализовать в нескольких строках кода:
Если вам когда-нибудь понадобится преобразовать данные между 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
...