Cách tốt nhất để xử lý các tài liệu XML, XSD, v.v. trong C # 2.0 là gì?
Sử dụng các lớp nào, v.v. Các phương pháp hay nhất để phân tích cú pháp và tạo tài liệu XML là gì, v.v.
CHỈNH SỬA: Đề xuất .Net 3.5 cũng được hoan nghênh.
Cách tốt nhất để xử lý các tài liệu XML, XSD, v.v. trong C # 2.0 là gì?
Sử dụng các lớp nào, v.v. Các phương pháp hay nhất để phân tích cú pháp và tạo tài liệu XML là gì, v.v.
CHỈNH SỬA: Đề xuất .Net 3.5 cũng được hoan nghênh.
Câu trả lời:
Phương tiện chính để đọc và viết trong C # 2.0 được thực hiện thông qua lớp XmlDocument . Bạn có thể tải trực tiếp hầu hết các cài đặt của mình vào XmlDocument thông qua XmlReader mà nó chấp nhận.
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);
Tôi thấy cách dễ nhất / nhanh nhất để đọc một tài liệu XML là sử dụng 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");
Nếu bạn cần làm việc với các tài liệu XSD để xác thực tài liệu XML, bạn có thể sử dụng nó.
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();
(CẬP NHẬT 1)
Trong .NET 3.5, bạn sử dụng XDocument để thực hiện các tác vụ tương tự. Tuy nhiên, sự khác biệt là bạn có lợi thế khi thực hiện Truy vấn Linq để chọn chính xác dữ liệu bạn cần. Với việc bổ sung các trình khởi tạo đối tượng, bạn có thể tạo một truy vấn thậm chí trả về các đối tượng theo định nghĩa của riêng bạn ngay trong chính truy vấn.
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();
(CẬP NHẬT 2)
Dưới đây là một cách hay trong .NET 3.5 là sử dụng XDocument để tạo XML. Điều này làm cho mã xuất hiện trong một mẫu tương tự với đầu ra mong muốn.
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")
)
)
);
tạo ra
<!--Xml Document-->
<catalog>
<book id="bk001">
<title>Book Title</title>
</book>
</catalog>
Vẫn thất bại, bạn có thể xem bài viết MSDN này có nhiều ví dụ mà tôi đã thảo luận ở đây và hơn thế nữa. http://msdn.microsoft.com/en-us/library/aa468556.aspx
Nó phụ thuộc vào kích thước; đối với xml kích thước nhỏ đến trung bình, một DOM như XmlDocument (bất kỳ phiên bản C # /. NET nào) hoặc XDocument (.NET 3.5 / C # 3.0) là người chiến thắng rõ ràng. Để sử dụng xsd, Bạn có thể tải xml bằng XmlReader và XmlReader chấp nhận (để Tạo ) XmlReaderSettings . Các đối tượng XmlReaderSettings có thuộc tính Schemas có thể được sử dụng để thực hiện xác thực xsd (hoặc dtd).
Đối với việc viết xml, những điều tương tự cũng áp dụng, lưu ý rằng việc bố trí nội dung với LINQ-to-XML (XDocument) dễ dàng hơn một chút so với XmlDocument cũ hơn.
Tuy nhiên, đối với xml lớn, DOM có thể chiếm quá nhiều bộ nhớ, trong trường hợp đó bạn có thể cần sử dụng trực tiếp XmlReader / XmlWriter.
Cuối cùng, để thao tác với xml, bạn có thể muốn sử dụng XslCompiledTransform (một lớp xslt).
Giải pháp thay thế để làm việc với xml là làm việc với một mô hình đối tượng; bạn có thể sử dụng xsd.exe để tạo các lớp đại diện cho một mô hình tuân thủ xsd và chỉ cần tải xml dưới dạng các đối tượng , thao tác với nó với OO, sau đó tuần tự hóa lại các đối tượng đó; bạn làm điều này với XmlSerializer .
câu trả lời của nyxtom rất hay. Tôi muốn thêm một số thứ vào nó:
Nếu bạn cần quyền truy cập chỉ đọc vào một tài liệu XML, đó XPathDocument
là một đối tượng có trọng lượng nhẹ hơn nhiều XmlDocument
.
Nhược điểm của việc sử dụng XPathDocument
là bạn không thể sử dụng các phương pháp quen thuộc SelectNodes
và SelectSingleNode
của XmlNode
. Thay vào đó, bạn phải sử dụng các công cụ mà nó IXPathNavigable
cung cấp: sử dụng CreateNavigator
để tạo XPathNavigator
và sử dụng XPathNavigator
để tạo XPathNodeIterator
s để lặp lại danh sách các nút bạn tìm thấy qua XPath. Điều này thường yêu cầu một vài dòng mã hơn các XmlDocument
phương thức.
Nhưng: các lớp XmlDocument
và XmlNode
thực thi IXPathNavigable
, vì vậy bất kỳ mã nào bạn viết để sử dụng các phương thức đó trên an XPathDocument
cũng sẽ hoạt động trên an XmlDocument
. Nếu bạn đã quen với việc viết ngược IXPathNavigable
, các phương thức của bạn có thể hoạt động với một trong hai đối tượng. (Đây là lý do tại sao sử dụng XmlNode
và XmlDocument
trong các chữ ký phương thức được FxCop gắn cờ.)
Đáng tiếc, XDocument
và XElement
(và XNode
và XObject
) không thực hiện IXPathNavigable
.
Một điều khác không có trong câu trả lời của nyxtom là XmlReader
. Bạn thường sử dụng XmlReader
để tránh chi phí phân tích luồng XML thành một mô hình đối tượng trước khi bạn bắt đầu xử lý nó. Thay vào đó, bạn sử dụng một XmlReader
để xử lý luồng đầu vào một nút XML tại một thời điểm. Đây thực chất là câu trả lời của .NET cho SAX. Nó cho phép bạn viết mã rất nhanh để xử lý các tài liệu XML rất lớn.
XmlReader
cũng cung cấp cách đơn giản nhất để xử lý các phân đoạn tài liệu XML, ví dụ: luồng các phần tử XML không có phần tử bao gồm mà tùy chọn FOR XML RAW của SQL Server trả về.
Mã bạn viết bằng cách sử dụng XmlReader
thường được kết hợp rất chặt chẽ với định dạng của XML mà nó đang đọc. Sử dụng XPath cho phép mã của bạn được kết hợp lỏng lẻo hơn nhiều với XML, đó là lý do tại sao nó thường là câu trả lời đúng. Nhưng khi bạn cần sử dụng XmlReader
, bạn thực sự cần nó.
XPathNavigator CreateNavigator(this XNode node)
để tạo một XPathNavigator
từ an XNode
(bao gồm lớp dẫn xuất XDocument
).
Trước hết, hãy làm quen với các lớp XDocument và XElement mới , vì chúng là một cải tiến so với họ XmlDocument trước đó.
Tuy nhiên , bạn có thể vẫn phải sử dụng các lớp cũ để làm việc với mã kế thừa - đặc biệt là các proxy đã tạo trước đó. Trong trường hợp đó, bạn sẽ cần phải làm quen với một số mẫu để tương tác giữa các lớp xử lý XML này.
Tôi nghĩ câu hỏi của bạn khá rộng và sẽ đòi hỏi quá nhiều trong một câu trả lời duy nhất để cung cấp thông tin chi tiết, nhưng đây là câu trả lời chung đầu tiên tôi nghĩ đến và coi như là một khởi đầu.
101 mẫu Linq
http://msdn.microsoft.com/en-us/library/bb387098.aspx
và Linq sang các mẫu XML
http://msdn.microsoft.com/en-us/vbasic/bb688087.aspx
Và tôi nghĩ Linq làm cho XML dễ dàng.
Nếu bạn đang làm việc trong .NET 3.5 và bạn không có mã thử nghiệm, bạn có thể kiểm tra LINQ to XSD ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to- xsd-alpha-0-2.aspx ) sẽ tạo ra các lớp .NET từ XSD (bao gồm cả các quy tắc tích hợp sẵn từ XSD).
Sau đó, nó có khả năng ghi thẳng ra tệp và đọc từ tệp đảm bảo rằng nó tuân thủ các quy tắc XSD.
Tôi chắc chắn khuyên bạn nên có một XSD cho bất kỳ tài liệu XML nào mà bạn làm việc:
Tôi thấy rằng Liquid XML Studio là một công cụ tuyệt vời để tạo XSD và hoàn toàn miễn phí!
Viết XML với lớp 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>
Ý kiến cá nhân của tôi, với tư cách là một lập trình viên C #, là cách tốt nhất để xử lý XML trong C # là ủy quyền phần mã đó cho một dự án VB .NET. Trong .NET 3.5, VB .NET có XML Literals, giúp xử lý XML trực quan hơn nhiều. Xem ví dụ ở đây:
Tổng quan về LINQ sang XML trong Visual Basic
(Đảm bảo đặt trang để hiển thị mã VB, không phải mã C #.)
Tôi muốn viết phần còn lại của dự án bằng C #, nhưng xử lý XML trong một dự án VB được tham chiếu.
nyxtom,
"Doc" và "xdoc" không nên khớp trong Ví dụ 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();
Câu trả lời của Cookey là tốt ... nhưng đây là hướng dẫn chi tiết về cách tạo một đối tượng được đánh máy mạnh từ XSD (hoặc XML) và tuần tự hóa / deserialize trong một vài dòng mã:
Nếu bạn cần chuyển đổi dữ liệu giữa XmlNode
<=> XNode
<=> XElement
(ví dụ: để sử dụng LINQ), Phần mở rộng này có thể hữu ích cho bạn:
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);
}
}
Sử dụng:
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
...