在C#2.0中处理XML文档,XSD等的最佳方法是什么?
使用哪些类等。解析和制作XML文档等的最佳实践是什么。
编辑:.Net 3.5建议也欢迎。
在C#2.0中处理XML文档,XSD等的最佳方法是什么?
使用哪些类等。解析和制作XML文档等的最佳实践是什么。
编辑:.Net 3.5建议也欢迎。
Answers:
C#2.0中的主要读写方法是通过XmlDocument类完成的。您可以通过接受的XmlReader将大多数设置直接加载到XmlDocument中。
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,明显的赢家是诸如XmlDocument(任何C#/。NET版本)或XDocument(.NET 3.5 / C#3.0)之类的DOM 。对于使用xsd,可以使用XmlReader加载xml ,并且XmlReader接受(创建)XmlReaderSettings。XmlReaderSettings对象具有一个架构属性,可用于执行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
,则您的方法可以针对任一对象。(这就是FxCop标记使用XmlNode
和XmlDocument
方法签名的原因。)
可悲的是,XDocument
and XElement
(和XNode
and XObject
)没有实现IXPathNavigable
。
nyxtom的答案中没有出现的另一件事是XmlReader
。通常XmlReader
,您可以避免在开始处理XML流之前将其解析为对象模型的开销。相反,您可以使用XmlReader
来一次处理一个XML节点的输入流。从本质上讲,这是.NET对SAX的回答。它使您可以编写非常快速的代码来处理非常大的XML文档。
XmlReader
它还提供了处理XML文档片段的最简单方法,例如,不包含SQL Server的FOR XML RAW选项返回的包含元素的XML元素流。
您编写的代码XmlReader
通常与所读取的XML格式紧密相关。使用XPath可以使您的代码与XML紧密得多地耦合,这就是为什么它通常是正确的答案。但是,当您需要使用时XmlReader
,您确实需要它。
XPathNavigator CreateNavigator(this XNode node)
可XPathNavigator
从创建扩展名XNode
(包括派生类XDocument
)。
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变得容易。
如果您使用的是.NET 3.5,并且不喜欢实验代码,则可以查看LINQ to XSD(http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to- xsd-alpha-0-2.aspx),它将从XSD生成.NET类(包括来自XSD的内置规则)。
然后,它可以直接写出文件并从文件中读取,以确保它符合XSD规则。
我绝对建议为您使用的任何XML文档使用XSD:
我发现Liquid XML Studio是生成XSD的绝佳工具,它是免费的!
使用XmlDocument类编写XML
//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#程序员,我个人的观点是,用C#处理XML的最佳方法是将那部分代码委托给VB .NET项目。在.NET 3.5中,VB .NET具有XML文字,使处理XML更加直观。例如,请参见此处:
(确保将页面设置为显示VB代码,而不是C#代码。)
我将用C#编写项目的其余部分,但在引用的VB项目中处理XML。
nyxtom,
示例1中的“ doc”和“ xdoc”不应该匹配吗?
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();
如果您需要在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
...