Como lidar com XML em C#
Qual é a melhor maneira de lidar com documentos XML, XSD etc Em C# 2.0?
quais as classes a utilizar, etc. Quais são as melhores práticas de processar e fazer documentos XML, etc.
editar:. Net 3. 5 sugestões também são bem-vindas.
12 answers
O principal meio de leitura e escrita em C# 2.0 é feito através da classe XmlDocument. Você pode carregar a maioria de suas configurações diretamente no XmlDocument através do XmlReader que ele aceita.
A carregar o XML directamente
XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");
A carregar XML de um ficheiro
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);
Acho que a maneira mais fácil/rápida de ler um documento XML é usando o XPath.
Ler um documento XML usando o XPath (usando o XmlDocument que nos permite editar)
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");
Se precisar de trabalhar com documentos XSD para validar um documento XML, pode usar isto.
A validar documentos XML com os esquemas do XSD
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); }
Validando XML contra XSD em cada nó (UPDATE 1)
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
}
A escrever um documento XML (manualmente)
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();
(actualizar 1)
No. net 3. 5, você usa o XDocument para executar tarefas semelhantes. A diferença no entanto é que você tem a vantagem de realizar consultas Linq para seleccione os dados exactos de que necessita. Com a adição de inicializadores de objetos Você pode criar uma consulta que até mesmo retorna objetos de sua própria definição direita na consulta em si.
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();
(actualizar 2)
Uma boa maneira no. net 3. 5 é usar o XDocument para criar o XML está em baixo. Isso faz com que o código apareça em um padrão semelhante à saída desejada.
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")
)
)
);
Cria
<!--Xml Document-->
<catalog>
<book id="bk001">
<title>Book Title</title>
</book>
</catalog>
Tudo o resto falha, você pode verificar este artigo MSDN que tem muitos exemplos que discuti aqui e mais. http://msdn.microsoft.com/en-us/library/aa468556.aspx
Depende do tamanho; para xml pequeno a médio, um DOM como XmlDocument (qualquer versão C#/. NET) ou XDocument (. net 3.5/C# 3.0) é o vencedor óbvio. Para usar o xsd, poderá carregar o xml usando um XmlReader , e um XmlReader aceita (para Create ) an XmlReaderSettings . Os objectos XmlReaderSettings têm uma propriedade Schemas que pode ser usada para efectuar a validação do xsd (ou dtd).
Para escrever xml, aplicam-se as mesmas coisas, notando que é um pouco mais fácil de colocar conteúdo com LINQ-to-XML (XDocument) do que o XmlDocument mais antigo.
No entanto, para o enorme xml, um DOM pode carregar demasiada memória, caso em que poderá ter de usar o XmlReader/XmlWriter directamente.
Finalmente, para manipular xml, poderá querer usar XslCompiledTransform (uma camada xslt).
A alternativa para trabalhar com xml é trabalhar com um modelo de objecto; você pode usar xsd.exe para criar classes que representar um modelo compatível com o xsd, e simplesmente carregar o xml como objectos, manipulá-lo com OO, e depois serializar esses objectos de novo; faça isto com Xmlserializador.
Se precisar de acesso apenas para leitura a um documento XML, {[[0]} é um objecto muito mais leve do que XmlDocument
.
A desvantagem de usar {[[0]} é que não pode usar os métodos familiares SelectNodes
e SelectSingleNode
de XmlNode
. Em vez disso, você tem que usar as ferramentas que o IXPathNavigable
oferece: use CreateNavigator
para criar um XPathNavigator
, e use o XPathNavigator
para criar XPathNodeIterator
s para iterar sobre as listas de nós que você encontra através do XPath. Presente geralmente requer mais algumas linhas de código do que os métodos XmlDocument
.
Mas: as classes XmlDocument
e XmlNode
implementam IXPathNavigable
, por isso qualquer código que escreva para usar esses métodos NUM XPathDocument
também funcionará num XmlDocument
. Se você se acostumar a escrever contra IXPathNavigable
, seus métodos podem funcionar contra qualquer um dos objetos. (É por isso que o uso de XmlNode
e XmlDocument
no método as assinaturas são assinaladas pelo FxCop.)
Lamentavelmente, XDocument
e XElement
(e XNode
e XObject
) não implementar IXPathNavigable
.
XmlReader
. Normalmente usa XmlReader
para evitar a sobrecarga de processar a transmissão XML num modelo de objecto antes de começar a processá-la. Em vez disso, você usa um XmlReader
para processar o fluxo de entrada de um nó XML de cada vez. Esta é essencialmente a resposta da. NET ao saxofone. Permite-lhe escrever um código muito rápido para processar documentos XML muito grandes.
XmlReader
também fornece a forma mais simples de processar fragmentos de documentos XML, por exemplo, o fluxo de elementos XML sem o elemento de inclusão que o servidor de SQL para a opção XML RAW devolve.
O código que se escreve usando XmlReader
é geralmente muito estreitamente associado ao formato do XML que está a ler. O uso do XPath permite que seu código seja muito, muito mais vagamente acoplado ao XML, e é por isso que geralmente é a resposta certa. Mas quando você precisa usar XmlReader
, você realmente precisa.
Em primeiro lugar, conheça as novas classes XDocument e XElement, porque são uma melhoria em relação à anterior família XmlDocument.
-
Eles trabalham com o LINQ.
- Eles são mais rápidos e mais leves
No entanto , você ainda pode ter que usar as classes antigas para trabalhar com o código legado - particularmente os proxies gerados anteriormente. Nesse caso, você terá que se familiarizar com alguns padrões para interoperar entre estas classes de tratamento de XML.
Acho que a sua pergunta é bastante ampla, e exigiria muito numa única resposta para dar detalhes, mas esta é a primeira resposta geral em que pensei, e serve como um começo.101 amostras de Linq
Http://msdn.microsoft.com/en-us/library/bb387098.aspx
E Linq para amostras XML
E acho que o Linq facilita o XML.Se está a trabalhar no. NET 3.5 e não tem medo de um código experimental, pode verificar o LINQ no XSD ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to-xsd-alpha-0-2.aspx ) que irá gerar classes. NET a partir de um XSD (incluindo as regras incorporadas no XSD).
Ele então tem a capacidade de escrever diretamente para um arquivo e ler a partir de um arquivo garantindo que ele está em conformidade com as regras do XSD.
Eu definitivamente sugiro ter um XSD para qualquer documento XML que você trabalhe com:
- permite-lhe fazer cumprir as regras no XML
- permite que outros vejam como o XML é / será estruturado
- pode ser usado para a validação de XML
Se você criar um conjunto de dados digitado no designer, então você automaticamente recebe um xsd, um objeto fortemente digitado, e pode carregar e salvar o xml com uma linha de código.
A minha opinião pessoal, como programador C#, é que a melhor maneira de lidar com XML em C# é delegar essa parte do código a um projecto VB.net. In. net 3.5, VB. net has XML Literals, which make dealing with XML much more intuitive. Veja aqui, por exemplo:
Visão Geral da LINQ para XML no Visual Basic
(Certifique-se que configura a página para mostrar o código VB, não o código C#.)
Eu escreveria o resto do projecto em C#, mas lidaria com o XML num VB referenciado. projecto.A escrever XML com a classe 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>
Nyxtom,
O "doc" e o "xdoc" não devem corresponder no exemplo 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();
Se alguma vez precisar de converter dados entre XmlNode
XNode
XElement
(por exemplo, para usar o LINQ) estas extensões podem ser úteis para si:
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);
}
}
Utilização:
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
...