Який найкращий спосіб мати справу з 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 мають властивість Schemas, яке можна використовувати для перевірки xsd (або dtd).
Для написання xml застосовуються ті самі речі, зазначаючи, що розкласти вміст за допомогою LINQ-to-XML (XDocument) трохи простіше, ніж старіший XmlDocument.
Однак для величезного xml DOM може втратити занадто багато пам'яті, і в цьому випадку вам може знадобитися використовувати XmlReader / XmlWriter.
Нарешті, для маніпулювання xml ви можете використовувати XslCompiledTransform (шар xslt).
Альтернативою роботі з xml є робота з об’єктною моделлю; Ви можете використовувати xsd.exe для створення класів, що представляють xsd-сумісну модель, і просто завантажити xml як об'єкти , маніпулювати ним за допомогою OO, а потім знову серіалізувати ці об'єкти; ви робите це за допомогою XmlSerializer .
Відповідь nyxtom дуже хороша. Я додав би до нього кілька речей:
Якщо вам потрібен доступ лише для читання до XML-документа, XPathDocumentце набагато легший об'єкт, ніж XmlDocument.
Недоліком використання XPathDocumentє те, що ви не можете використовувати звичні SelectNodesта SelectSingleNodeметоди XmlNode. Натомість вам доведеться скористатися інструментами, які IXPathNavigableнадає: використовуйте CreateNavigatorдля створення XPathNavigatorта використовуйте XPathNavigatorдля створення XPathNodeIteratorдля перебору списків вузлів, знайдених за допомогою 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>
Якщо ви створили набраний набір даних у конструкторі, ви автоматично отримуєте xsd, сильно набраний об'єкт, і можете завантажувати та зберігати xml одним рядком коду.
Моя особиста думка, як програміста на 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();
Відповідь Cookey хороша ... але ось докладні інструкції про те, як створити сильно набраний об'єкт із 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
...