วิธีที่ดีที่สุดในการจัดการกับเอกสาร 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 เพื่อทำงานที่คล้ายกัน ความแตกต่างคือคุณมีข้อได้เปรียบในการดำเนินการ Queries 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 ลงในโมเดลอ็อบเจ็กต์ก่อนที่คุณจะเริ่มประมวลผล คุณใช้ an 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 ถึง 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 Literals ซึ่งทำให้จัดการกับ XML ได้ง่ายขึ้นมาก ดูที่นี่ตัวอย่าง:
ภาพรวมของ LINQ เป็น XML ใน Visual Basic
(อย่าลืมตั้งค่าหน้าให้แสดงรหัส VB ไม่ใช่รหัส C #)
ฉันจะเขียนส่วนที่เหลือของโครงการใน C # แต่จัดการ XML ในโครงการ VB ที่อ้างอิง
nyxtom,
"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) และทำให้เป็นอนุกรม / deserialize ในโค้ดไม่กี่บรรทัด:
หากคุณต้องการแปลงข้อมูลระหว่าง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
...