Qual é a melhor maneira de lidar com documentos XML, XSD etc. em C # 2.0?
Quais classes usar etc. Quais são as melhores práticas de análise e criação de documentos XML, etc.
EDIT: .Net 3.5 sugestões também são bem-vindas.
Qual é a melhor maneira de lidar com documentos XML, XSD etc. em C # 2.0?
Quais classes usar etc. Quais são as melhores práticas de análise e criação de documentos XML, etc.
EDIT: .Net 3.5 sugestões também são bem-vindas.
Respostas:
O principal meio de leitura e gravação em C # 2.0 é feito por meio da classe XmlDocument . Você pode carregar a maioria de suas configurações diretamente no XmlDocument por meio do XmlReader que ele aceita.
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);
Acho que a maneira mais fácil / rápida de ler um documento XML é usando 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");
Se você precisa trabalhar com documentos XSD para validar um documento XML, você pode usar isso.
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();
(ATUALIZAÇÃO 1)
No .NET 3.5, você usa o XDocument para executar tarefas semelhantes. A diferença, entretanto, é que você tem a vantagem de realizar Consultas Linq para selecionar os dados exatos de que precisa. Com a adição de inicializadores de objeto, você pode criar uma consulta que retorna até mesmo objetos de sua própria definição diretamente na própria consulta.
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();
(ATUALIZAÇÃO 2)
Uma boa maneira no .NET 3.5 é usar o XDocument para criar XML abaixo. 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>
Se tudo o mais falhar, você pode verificar este artigo do MSDN que tem muitos exemplos que discuti aqui e mais. http://msdn.microsoft.com/en-us/library/aa468556.aspx
Depende do tamanho; para xml de tamanho 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, você pode carregar o xml usando um XmlReader , e um XmlReader aceita (para criar ) um XmlReaderSettings . Os objetos XmlReaderSettings têm uma propriedade Schemas que pode ser usada para executar a validação xsd (ou dtd).
Para escrever xml, as mesmas coisas se aplicam, observando que é um pouco mais fácil fazer o layout do conteúdo com LINQ-to-XML (XDocument) do que o XmlDocument mais antigo.
No entanto, para xml enorme, um DOM pode consumir muita memória e, nesse caso, você pode precisar usar XmlReader / XmlWriter diretamente.
Finalmente, para manipular xml, você pode querer usar XslCompiledTransform (uma camada xslt).
A alternativa para trabalhar com xml é trabalhar com um modelo de objeto; você pode usar xsd.exe para criar classes que representam um modelo compatível com xsd e simplesmente carregar o xml como objetos , manipulá-lo com OO e serializar esses objetos novamente; você faz isso com XmlSerializer .
A resposta da nyxtom é muito boa. Eu adicionaria algumas coisas a ele:
Se você precisar de acesso somente leitura a um documento XML, XPathDocument
é um objeto muito mais leve do que XmlDocument
.
A desvantagem de usar XPathDocument
é que você não pode usar os métodos SelectNodes
e SelectSingleNode
métodos familiares de XmlNode
. Em vez disso, você deve usar as ferramentas que o IXPathNavigable
fornece: use CreateNavigator
para criar um XPathNavigator
e use XPathNavigator
para criar XPathNodeIterator
s para iterar nas listas de nós que você encontrar por meio do XPath. Isso geralmente requer mais algumas linhas de código do que os XmlDocument
métodos.
Mas: as classes XmlDocument
e XmlNode
implementam IXPathNavigable
, portanto, qualquer código que você escrever para usar esses métodos em um XPathDocument
também funcionará em um XmlDocument
. Se você se acostumar a escrever contra IXPathNavigable
, seus métodos podem funcionar contra qualquer um dos objetos. (É por isso que usar XmlNode
e XmlDocument
em assinaturas de método é sinalizado pelo FxCop.)
Lamentavelmente, XDocument
and XElement
(and XNode
and XObject
) não implementam IXPathNavigable
.
Outra coisa que não está presente na resposta de nyxtom é XmlReader
. Você geralmente usa XmlReader
para evitar a sobrecarga de analisar o fluxo XML em um modelo de objeto antes de começar a processá-lo. Em vez disso, use um XmlReader
para processar o fluxo de entrada um nó XML por vez. Esta é essencialmente a resposta do .NET para SAX. Ele permite que você escreva um código muito rápido para processar documentos XML muito grandes.
XmlReader
também fornece a maneira mais simples de processar fragmentos de documentos XML, por exemplo, o fluxo de elementos XML sem nenhum elemento de inclusão que a opção FOR XML RAW do SQL Server retorna.
O código que você escreve usando XmlReader
geralmente está fortemente acoplado ao formato do XML que está lendo. Usar 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.
XPathNavigator CreateNavigator(this XNode node)
para criar um XPathNavigator
de um XNode
(que inclui a classe derivada XDocument
).
Em primeiro lugar, conheça as novas classes XDocument e XElement , porque são uma melhoria em relação à família XmlDocument anterior.
No entanto , talvez você ainda precise usar as classes antigas para trabalhar com código legado - particularmente proxies gerados anteriormente. Nesse caso, você precisará se familiarizar com alguns padrões para interoperar entre essas classes de manipulação de XML.
Acho que sua pergunta é bastante ampla e exigiria muito em uma única resposta para fornecer detalhes, mas esta é a primeira resposta geral em que pensei e serve como um começo.
101 amostras Linq
http://msdn.microsoft.com/en-us/library/bb387098.aspx
e Linq para amostras XML
http://msdn.microsoft.com/en-us/vbasic/bb688087.aspx
E acho que o Linq torna o XML fácil.
Se você está trabalhando em .NET 3.5 e não tem medo de código experimental, pode verificar LINQ to 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 regras embutidas do XSD).
Em seguida, ele tem a capacidade de gravar diretamente em um arquivo e ler de um arquivo, garantindo que ele esteja em conformidade com as regras XSD.
Definitivamente, sugiro ter um XSD para qualquer documento XML com o qual você trabalha:
Acho que Liquid XML Studio é uma ótima ferramenta para gerar XSDs e é grátis!
Escrevendo 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>
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 projeto VB .NET. No .NET 3.5, o VB .NET possui XML Literals, o que torna o tratamento de XML muito mais intuitivo. Veja aqui, por exemplo:
Visão geral do LINQ to XML no Visual Basic
(Certifique-se de definir a página para exibir o código VB, não o código C #.)
Eu escreveria o resto do projeto em C #, mas lidaria com o XML em um projeto VB referenciado.
nyxtom,
"Doc" e "xdoc" não deveriam 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();
A resposta de Cookey é boa ... mas aqui estão instruções detalhadas sobre como criar um objeto fortemente tipado a partir de um XSD (ou XML) e serializar / desserializar em algumas linhas de código:
Se você precisar converter dados entre XmlNode
<=> XNode
<=> XElement
(por exemplo, para usar o LINQ), essas extensões podem ser úteis para você:
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);
}
}
Uso:
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
...