Qual è il modo migliore per gestire documenti XML, XSD ecc. In C # 2.0?
Quali classi utilizzare ecc. Quali sono le migliori pratiche per analizzare e creare documenti XML, ecc.
EDIT: anche i suggerimenti .Net 3.5 sono i benvenuti.
Qual è il modo migliore per gestire documenti XML, XSD ecc. In C # 2.0?
Quali classi utilizzare ecc. Quali sono le migliori pratiche per analizzare e creare documenti XML, ecc.
EDIT: anche i suggerimenti .Net 3.5 sono i benvenuti.
Risposte:
Il mezzo principale di lettura e scrittura in C # 2.0 viene eseguito tramite la classe XmlDocument . È possibile caricare la maggior parte delle impostazioni direttamente in XmlDocument tramite XmlReader che accetta.
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);
Trovo che il modo più semplice / veloce per leggere un documento XML sia usare 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 è necessario lavorare con documenti XSD per convalidare un documento XML, è possibile utilizzarlo.
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();
(AGGIORNAMENTO 1)
In .NET 3.5 si utilizza XDocument per eseguire attività simili. La differenza, tuttavia, è che hai il vantaggio di eseguire query Linq per selezionare i dati esatti di cui hai bisogno. Con l'aggiunta di inizializzatori di oggetti è possibile creare una query che restituisce anche oggetti di propria definizione direttamente nella query stessa.
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();
(AGGIORNAMENTO 2)
Un bel modo in .NET 3.5 è usare XDocument per creare XML è sotto. Questo fa apparire il codice in un modello simile all'output desiderato.
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")
)
)
);
crea
<!--Xml Document-->
<catalog>
<book id="bk001">
<title>Book Title</title>
</book>
</catalog>
Tutto il resto fallisce, puoi consultare questo articolo MSDN che contiene molti esempi che ho discusso qui e altro ancora. http://msdn.microsoft.com/en-us/library/aa468556.aspx
Dipende dalle dimensioni; per XML di piccole e medie dimensioni, un DOM come XmlDocument (qualsiasi versione C # /. NET) o XDocument (.NET 3.5 / C # 3.0) è il vincitore ovvio. Per l'utilizzo di xsd, è possibile caricare xml utilizzando un XmlReader e un XmlReader accetta (per creare ) un XmlReaderSettings . Gli oggetti XmlReaderSettings hanno schemi proprietà che può essere utilizzata per eseguire la convalida xsd (o dtd).
Per la scrittura di xml, si applicano le stesse cose, notando che è un po 'più facile disporre il contenuto con LINQ-to-XML (XDocument) rispetto al vecchio XmlDocument.
Tuttavia, per un XML enorme, un DOM potrebbe masticare troppa memoria, nel qual caso potrebbe essere necessario utilizzare XmlReader / XmlWriter direttamente.
Infine, per manipolare xml potresti voler usare XslCompiledTransform (un livello xslt).
L'alternativa a lavorare con xml è lavorare con un modello a oggetti; è possibile utilizzare xsd.exe per creare classi che rappresentano un modello conforme a xsd e caricare semplicemente l'xml come oggetti , manipolarlo con OO e quindi serializzare nuovamente quegli oggetti; lo fai con XmlSerializer .
La risposta di nyxtom è molto buona. Aggiungerei un paio di cose:
Se è necessario l'accesso in sola lettura a un documento XML, XPathDocumentè un oggetto molto più leggero di XmlDocument.
Lo svantaggio dell'utilizzo XPathDocumentè che non puoi usare i metodi familiari SelectNodese SelectSingleNodedi XmlNode. Invece, devi usare gli strumenti che IXPathNavigablefornisce: usa CreateNavigatorper creare un XPathNavigatore usa XPathNavigatorper creare XPathNodeIterators per scorrere gli elenchi di nodi che trovi tramite XPath. Ciò richiede generalmente alcune righe di codice in più rispetto aXmlDocument metodi.
Ma: le classi XmlDocumente vengono XmlNodeimplementate IXPathNavigable, quindi qualsiasi codice che scrivi per usare questi metodi su un file XPathDocumentfunzionerà anche su un file XmlDocument. Se ti abitui a scrivere contro IXPathNavigable, i tuoi metodi possono funzionare contro entrambi gli oggetti. (Questo è il motivo per cui l'utilizzo di XmlNodeeXmlDocument nelle firme del metodo è contrassegnato da FxCop.)
Purtroppo, XDocumente XElement(e XNodee XObject) non implementare IXPathNavigable.
Un'altra cosa non presente nella risposta di nyxtom è XmlReader. In genere si utilizza XmlReaderper evitare il sovraccarico di analizzare il flusso XML in un modello a oggetti prima di iniziare a elaborarlo. Invece, usi un fileXmlReader per elaborare il flusso di input un nodo XML alla volta. Questa è essenzialmente la risposta di .NET a SAX. Ti consente di scrivere codice molto veloce per l'elaborazione di documenti XML di grandi dimensioni.
XmlReader fornisce inoltre il modo più semplice per elaborare i frammenti di documenti XML, ad esempio il flusso di elementi XML senza elementi inclusi restituiti dall'opzione FOR XML RAW di SQL Server.
Il codice che scrivi usando XmlReaderè generalmente molto strettamente accoppiato al formato dell'XML che sta leggendo. L'uso di XPath consente al tuo codice di essere accoppiato molto, molto più liberamente all'XML, motivo per cui è generalmente la risposta giusta. Ma quando hai bisogno di usarlo XmlReader, ne hai davvero bisogno.
XPathNavigator CreateNavigator(this XNode node)per creare un XPathNavigatorda un XNode(che include la classe derivata XDocument).
Prima di tutto, impara a conoscere le nuove classi XDocument e XElement , perché sono un miglioramento rispetto alla precedente famiglia XmlDocument.
Tuttavia , potrebbe essere necessario utilizzare ancora le vecchie classi per lavorare con il codice legacy, in particolare i proxy generati in precedenza. In tal caso, sarà necessario acquisire familiarità con alcuni modelli per l'interoperabilità tra queste classi di gestione XML.
Penso che la tua domanda sia abbastanza ampia e richiederebbe troppo in una singola risposta per fornire dettagli, ma questa è la prima risposta generale a cui ho pensato e serve come inizio.
101 campioni Linq
http://msdn.microsoft.com/en-us/library/bb387098.aspx
e Linq agli esempi XML
http://msdn.microsoft.com/en-us/vbasic/bb688087.aspx
E penso che Linq renda XML facile.
Se stai lavorando in .NET 3.5 e non hai paura del codice sperimentale, puoi controllare LINQ to XSD ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to- xsd-alpha-0-2.aspx ) che genererà classi .NET da un XSD (comprese le regole incorporate dall'XSD).
Ha quindi la capacità di scrivere direttamente su un file e leggere da un file assicurandosi che sia conforme alle regole XSD.
Consiglio vivamente di avere un XSD per qualsiasi documento XML con cui lavori:
Trovo che Liquid XML Studio sia un ottimo strumento per generare XSD ed è gratuito!
Scrittura di XML con la 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>
La mia opinione personale, come programmatore C #, è che il modo migliore per gestire XML in C # è delegare quella parte del codice a un progetto VB .NET. In .NET 3.5, VB .NET ha XML Literals, che rendono la gestione di XML molto più intuitiva. Vedi qui, ad esempio:
Panoramica di LINQ to XML in Visual Basic
(Assicurati di impostare la pagina per visualizzare il codice VB, non il codice C #.)
Scriverei il resto del progetto in C #, ma gestirò l'XML in un progetto VB referenziato.
nyxtom,
"Doc" e "xdoc" non dovrebbero corrispondere nell'esempio 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();
La risposta di Cookey è buona ... ma qui ci sono istruzioni dettagliate su come creare un oggetto fortemente tipizzato da un XSD (o XML) e serializzare / deserializzare in poche righe di codice:
Se hai bisogno di convertire i dati tra XmlNode<=> XNode<=> XElement
(ad es. Per usare LINQ), queste estensioni potrebbero esserti utili:
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);
}
}
Utilizzo:
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
...