Otro requisito común es transformar XML en un formato diferente, convertir un XML a una forma diferente de XML, convertir XML en HTML, convertir texto en XML.
Lección 1: Trabajando con las clases XmlDocument y XmlReader
La clase XmlDocument
El W3C ha proporcionado las normas que definen la estructura y una interfaz de programación estándar llamado Document Object Model (DOM) que se pueden utilizar en una amplia variedad de entornos y aplicaciones para documentos XML.
Las clases XML son accesibles haciendo una referencia a System.Xml.dll y agregando Imports System.Xml (C # using System.Xml;) en el código.La clase XmlDocument es una representación en memoria de XML utilizando el DOM Nivel 1 y Nivel 2. Esta clase se puede utilizar para navegar y editar los nodos XML.
Hay otra clase, XmlDataDocument, que hereda de la clase XmlDocument y representa datos relacionales, se encuentra en System.Data.dll, Estas clases proporcionan varios métodos para implementar la especificación de nivel 2 y tienen métodos para facilitar las operaciones comunes. La clase XmlDocument, que hereda de XmlNode, contiene todos los métodos para la creación de elementos y atributos XML.
Nombre | Descripción |
AppendChild | Agrega el nodo especificado al final de la lista de nodos secundarios de este nodo. (Se hereda de XmlNode). |
Clone | Crea un duplicado de este nodo. (Se hereda de XmlNode). |
CloneNode | Crea un duplicado de este nodo. (Invalida a XmlNode.CloneNode(Boolean)). |
CreateAttribute(String) | Crea un XmlAttribute con el Name especificado. |
CreateAttribute(String, String) | Crea un XmlAttribute con el nombre completo y el NamespaceURI especificados. |
CreateAttribute(String, String, String) | Crea un XmlAttribute con los Prefix, LocalName y NamespaceURI especificados. |
CreateCDataSection | Crea un objeto XmlCDataSection que contiene los datos especificados. |
CreateComment | Crea un objeto XmlComment que contiene los datos especificados. |
CreateDefaultAttribute | Crea un atributo predeterminado con el prefijo, el nombre local y el identificador URI de espacio de nombres especificados. |
CreateDocumentFragment | Crea un objeto XmlDocumentFragment. |
CreateDocumentType | Devuelve un nuevo objeto XmlDocumentType. |
CreateElement(String) | Crea un elemento con el nombre especificado. |
CreateElement(String, String) | Crea un XmlElement con el nombre completo y el NamespaceURI. |
CreateElement(String, String, String) | Crea un elemento con los valores Prefix, LocalName y NamespaceURI especificados. |
CreateEntityReference | Crea un objeto XmlEntityReference con el nombre especificado. |
CreateNavigator | Crea un nuevo objeto XPathNavigator para navegar por este documento. (Invalida a XmlNode.CreateNavigator). |
CreateNavigator(XmlNode) | Crea un objeto XPathNavigator para navegar por este documento colocado en el nodo XmlNode especificado. |
CreateNode(String, String, String) | Crea un XmlNode con el tipo de nodo, Name y NamespaceURI especificados. |
CreateNode(XmlNodeType, String, String) | Crea un XmlNode con los XmlNodeType, Name y NamespaceURI especificados. |
CreateNode(XmlNodeType, String, String, String) | Crea un XmlNode con XmlNodeType, Prefix, Name y NamespaceURI especificados. |
CreateProcessingInstruction | Crea un objeto XmlProcessingInstruction con el nombre y los datos especificados. |
CreateSignificantWhitespace | Crea un nodo XmlSignificantWhitespace. |
CreateTextNode | Crea un objeto XmlText con el texto especificado. |
CreateWhitespace | Crea un nodo XmlWhitespace. |
CreateXmlDeclaration | Crea un nodo XmlDeclaration con los valores especificados. |
Equals(Object) | Determina si el objeto Object especificado es igual al objeto Object actual. (Se hereda de Object). |
Finalize | Permite que un objeto intente liberar recursos y realizar otras operaciones de limpieza antes de ser reclamado por la recolección de elementos no utilizados. (Se hereda de Object). |
GetElementById | Obtiene el XmlElement con el identificador especificado. |
GetElementsByTagName(String) | Devuelve un objeto XmlNodeList que contiene una lista de todos los elementos descendientes que coinciden con el Nameespecificado. |
GetElementsByTagName(String, String) | Devuelve un objeto XmlNodeList que contiene una lista de todos los elementos descendientes que coinciden con el LocalName y el NamespaceURI especificados. |
GetEnumerator | Proporciona funcionalidad para la iteración de estilo "foreach" en los nodos de XmlNode. (Se hereda de XmlNode). |
GetHashCode | Actúa como función hash para un tipo concreto. (Se hereda de Object). |
GetNamespaceOfPrefix | Busca la declaración xmlns más cercana para el prefijo especificado que está en el ámbito del nodo actual y devuelve el identificador URI de espacio de nombres de la declaración. (Se hereda de XmlNode). |
GetPrefixOfNamespace | Busca la declaración xmlns más cercana para el identificador URI de espacio de nombres especificado que está en el ámbito del nodo actual y devuelve el prefijo definido en la declaración. (Se hereda de XmlNode). |
GetType | Obtiene el objeto Type de la instancia actual. (Se hereda de Object). |
ImportNode | Importa un nodo de otro documento al documento actual. |
InsertAfter | Inserta el nodo especificado inmediatamente detrás del nodo de referencia igualmente especificado. (Se hereda deXmlNode). |
InsertBefore | Inserta el nodo especificado inmediatamente antes del nodo de referencia igualmente especificado. (Se hereda deXmlNode). |
Load(Stream) | Carga el documento XML desde la secuencia especificada. |
Load(String) | Carga el documento XML desde la dirección URL especificada. |
Load(TextReader) | Carga el documento XML desde el TextReader especificado. |
Load(XmlReader) | Carga el documento XML desde el XmlReader especificado. |
LoadXml | Carga el documento XML desde la cadena especificada. |
MemberwiseClone | Crea una copia superficial del objeto Object actual. (Se hereda de Object). |
Normalize | Hace que todos los nodos XmlText de toda la profundidad del subárbol situado bajo XmlNode aparezcan de forma "normal", de modo que sólo el marcado (es decir, las etiquetas, comentarios, instrucciones de procesamiento, secciones CDATA y referencias a entidades) separa los nodos XmlText, es decir, no hay nodos XmlText adyacentes. (Se hereda deXmlNode). |
PrependChild | Agrega el nodo especificado al principio de la lista de nodos secundarios de este nodo. (Se hereda de XmlNode). |
ReadNode | Crea un objeto XmlNode tomando como base la información de XmlReader. El lector debe estar situado en un nodo o en un atributo. |
RemoveAll | Quita todos los atributos y nodos secundarios del nodo actual. (Se hereda de XmlNode). |
RemoveChild | Quita el nodo secundario especificado. (Se hereda de XmlNode). |
ReplaceChild | Reemplaza el nodo secundario oldChild por el nodo newChild. (Se hereda de XmlNode). |
Save(Stream) | Guarda el documento XML en la secuencia especificada. |
Save(String) | Guarda el documento XML en el archivo especificado. |
Save(TextWriter) | Guarda el documento XML en el TextWriter especificado. |
Save(XmlWriter) | Guarda el documento XML en el XmlWriter especificado. |
SelectNodes(String) | Selecciona una lista de nodos que coinciden con la expresión XPath. (Se hereda de XmlNode). |
SelectNodes(String, XmlNamespaceManager) | Selecciona una lista de nodos que coinciden con la expresión XPath. Los prefijos encontrados en la expresión XPath se resuelven utilizando el XmlNamespaceManager proporcionado. (Se hereda de XmlNode). |
SelectSingleNode(String) | Selecciona el primer XmlNode que coincide con la expresión XPath. (Se hereda de XmlNode). |
SelectSingleNode(String, XmlNamespaceManager) | Selecciona el primer XmlNode que coincide con la expresión XPath. Los prefijos encontrados en la expresión XPath se resuelven utilizando el XmlNamespaceManager proporcionado. (Se hereda de XmlNode). |
Supports | Comprueba si la implementación de DOM incluye una característica específica. (Se hereda de XmlNode). |
ToString | Devuelve una cadena que representa el objeto actual. (Se hereda de Object). |
Validate(ValidationEventHandler) | Valida el objeto XmlDocument según los esquemas del lenguaje de definición de esquemas XML (XSD) de la propiedadSchemas. |
Validate(ValidationEventHandler, XmlNode) | Valida el objeto XmlNode especificado según los esquemas del lenguaje de definición de esquemas XML (XSD) de la propiedad Schemas. |
WriteContentTo | Guarda todos los nodos secundarios del nodo XmlDocument en el XmlWriter especificado. (Invalida aXmlNode.WriteContentTo(XmlWriter)). |
WriteTo | Guarda el nodo XmlDocument en el XmlWriter especificado. (Invalida a XmlNode.WriteTo(XmlWriter)). |
Creando un XmlDocument
El siguiente ejemplo muestra cómo se puede crear un XmlDocument y después guardarlo en un archivo. Se debe importar System.Xml y System.IO.
-----------------------------VB----------------------------------
‘creo el xmlDocument Dim xmlDoc As New XmlDocument() Dim el As XmlElement Dim childCounter As Integer Dim grandChildCounter As Integer ’Creo la declaracion xml y la agrego xmlDoc.AppendChild( _ xmlDoc.CreateXmlDeclaration("1.0", "utf-8", Nothing)) ’Creo un elemento y lo agrego el = xmlDoc.CreateElement("MyRoot") xmlDoc.AppendChild(el) For childCounter = 1 To 4 Dim childelmt As XmlElement Dim childattr As XmlAttribute ’creo un elemento y le agrego el atributo ID childelmt = xmlDoc.CreateElement("MyChild") childattr = xmlDoc.CreateAttribute("ID") childattr.Value = childCounter.ToString() childelmt.Attributes.Append(childattr) ’Agrego el elemento al elemento root el.AppendChild(childelmt) For grandChildCounter = 1 To 3 ’Creo el elemento nieto childelmt.AppendChild(xmlDoc.CreateElement("MyGrandChild")) Next Next ’lo guardo al archivo xmlDoc.Save(GetFilePath("XmlDocumentTest.xml")) txtLog.AppendText("XmlDocumentTest.xml Created" + vbCrLf) End Sub Private Function getFilePath(ByVal fileName As String) As String Return Path.Combine(Environment.GetFolderPath( _ Environment.SpecialFolder.Desktop), fileName) End Function
-----------------------------CS----------------------------------
//creo un XmlDocument var xmlDoc = new XmlDocument(); XmlElement el; int childCounter; int grandChildCounter; //genero la declaracion XML xmlDoc.AppendChild( xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null)); //Creo el nodo root y se lo agrego a xmldoc el = xmlDoc.CreateElement("MyRoot"); xmlDoc.AppendChild(el); for (childCounter = 1; childCounter <= 4; childCounter++) { //creo el elemento hijo con el atributo ID XmlElement childelmt; XmlAttribute childattr; childelmt = xmlDoc.CreateElement("MyChild"); childattr = xmlDoc.CreateAttribute("ID"); childattr.Value = childCounter.ToString(); childelmt.Attributes.Append(childattr); el.AppendChild(childelmt); for (grandChildCounter = 1; grandChildCounter <= 3; grandChildCounter++) { //Creo el elemnto nieto childelmt.AppendChild(xmlDoc.CreateElement("MyGrandChild")); } } //lo guardo en un archivo xmlDoc.Save(getFilePath("XmlDocumentTest.xml")); txtLog.AppendText("XmlDocumentTest.xml Created\r\n"); } private string getFilePath(string fileName) { return Path.Combine(Environment.GetFolderPath( Environment.SpecialFolder.Desktop), fileName); }
Archivo Xml resultante:
<?xml version="1.0" encoding="utf-8"?> <MyRoot> <MyChild ID="1"> <MyGrandChild /> <MyGrandChild /> <MyGrandChild /> </MyChild> <MyChild ID="2"> <MyGrandChild /> <MyGrandChild /> <MyGrandChild /> </MyChild> <MyChild ID="3"> <MyGrandChild /> <MyGrandChild /> <MyGrandChild /> </MyChild> <MyChild ID="4"> <MyGrandChild /> <MyGrandChild /> <MyGrandChild /> </MyChild> </MyRoot>
Análisis de un XmlDocument utilizando DOM
Un XmlDocument se puede analizar mediante el uso de una rutina recursiva para recorrer todos sus elementos.
-----------------------------VB----------------------------------
Private Sub ParsingAnXmlDocumentToolStripMenuItem_Click( _ ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles ParsingAnXmlDocumentToolStripMenuItem.Click Dim xmlDoc As New XmlDocument() xmlDoc.Load(getFilePath("XmlDocumentTest.xml")) RecurseNodes(xmlDoc.DocumentElement) End Sub Public Sub RecurseNodes(ByVal node As XmlNode) Dim sb As New StringBuilder() RecurseNodes(node, 0, sb) txtLog.Text = sb.ToString() End Sub Public Sub RecurseNodes( _ ByVal node As XmlNode, ByVal level As Integer, _ ByVal sb As StringBuilder) sb.AppendFormat("{0,2} Type:{1,-9} Name:{2,-13} Attr:", _ level, node.NodeType, node.Name) For Each attr As XmlAttribute In node.Attributes sb.AppendFormat("{0}={1} ", attr.Name, attr.Value) Next sb.AppendLine() For Each n As XmlNode In node.ChildNodes RecurseNodes(n, level + 1, sb) Next End Sub
-----------------------------CS----------------------------------
private void parsingAndXmlDocumentToolStripMenuItem_Click(object sender, EventArgs e) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(getFilePath("XmlDocumentTest.xml")); RecurseNodes(xmlDoc.DocumentElement); } public void RecurseNodes(XmlNode node) { var sb = new StringBuilder(); //empiezo el loop en el nivel 0 RecurseNodes(node, 0, sb); txtLog.Text = sb.ToString(); } public void RecurseNodes(XmlNode node, int level, StringBuilder sb) { sb.AppendFormat("{0,2} Type:{1,-9} Name:{2,-13} Attr:", level, node.NodeType, node.Name); foreach (XmlAttribute attr in node.Attributes) { sb.AppendFormat("{0}={1} ", attr.Name, attr.Value); } sb.AppendLine(); foreach (XmlNode n in node.ChildNodes) { RecurseNodes(n, level + 1, sb); } }
Este código empieza cargando un archivo XML y después llama al método RecurseNodes, que está sobrecargado. La primera llamada simplemente pasa el nodo raíz xmlDoc. La llamada recursiva pasa el nivel de recursión y un objeto de cadena de constructor.
Resultado obtenido:
0 Type:Element Name:MyRoot Attr: 1 Type:Element Name:MyChild Attr:ID=1 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr: 1 Type:Element Name:MyChild Attr:ID=2 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr: 1 Type:Element Name:MyChild Attr:ID=3 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr: 1 Type:Element Name:MyChild Attr:ID=4 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr: 2 Type:Element Name:MyGrandChild Attr:
Búsqueda en el XmlDocument
El método SelectSingleNode puede buscar un elemento, este requiere una consulta XPath. El siguiente ejemplo llama al método SelectSingleNode para localizar el elemento MyChild con ID 3.
-----------------------------VB----------------------------------
Dim xmlDoc As New XmlDocument() xmlDoc.Load(getFilePath("XmlDocumentTest.xml")) Dim node = xmlDoc.SelectSingleNode("//MyChild[@ID='3']") RecurseNodes(node) -----------------------------CS----------------------------------
var xmlDoc = new XmlDocument(); xmlDoc.Load(getFilePath("XmlDocumentTest.xml")); var node = xmlDoc.SelectSingleNode("//MyChild[@ID='3']"); RecurseNodes(node);
El resultado de la búsqueda seria:
0 Type:Element Name:MyChild Attr:ID=3
1 Type:Element Name:MyGrandChild Attr:
1 Type:Element Name:MyGrandChild Attr:
1 Type:Element Name:MyGrandChild Attr:
GetElementsByTagName
El método getElementsByTagName devuelve una lista de XmlNode contiene todos los elementos encontrados. El siguiente código devuelve una lista de nodos con el nombre de la etiqueta MyGrandChild.
-----------------------------VB----------------------------------
Dim elmts = xmlDoc.GetElementsByTagName("MyGrandChild")
-----------------------------CS----------------------------------
var elmts = xmlDoc.GetElementsByTagName("MyGrandChild");
SelectNodes
El método SelectNodes, requiere una consulta XPath y también puede recuperar una lista de XmlNode. El ejemplo de código anterior se ha modificado para llamar al método SelectNodes para lograr el mismo resultado:
-----------------------------VB----------------------------------
Dim elmts = xmlDoc.SelectNodes("//MyGrandChild")
-----------------------------CS----------------------------------
var elmts = xmlDoc.SelectNodes("//MyGrandChild");
La clase XmlReader
La clase XmlReader es una clase base abstracta que proporciona métodos para leer y analizar XML, sólo hacia delante, de acceso noncaching a una secuencia de datos XML.
Esta clase es ideal cuando la información deseada se encuentra en la parte superior del archivo XML y el archivo es grande. Si se necesita acceso al azar, se utiliza la clase XmlDocument.
-----------------------------VB----------------------------------
Dim sb As New StringBuilder() Dim xmlReader As New _ XmlTextReader(getFilePath("XmlDocumentTest.xml")) Do While xmlReader.Read() Select Case xmlReader.NodeType Case XmlNodeType.XmlDeclaration, _ XmlNodeType.Element, _ XmlNodeType.Comment Dim s As String sb.AppendFormat("{0}: {1} = {2}", _ xmlReader.NodeType, _ xmlReader.Name, _ xmlReader.Value) sb.AppendLine() Case XmlNodeType.Text Dim s As String sb.AppendFormat(" - Value: {0}", _ xmlReader.Value) sb.AppendLine() End Select If xmlReader.HasAttributes Then Do While xmlReader.MoveToNextAttribute() sb.AppendFormat(" - Attribute: {0} = {1}", _ xmlReader.Name, xmlReader.Value) sb.AppendLine() Loop End If Loop xmlReader.Close() txtLog.Text = sb.ToString()
-----------------------------CS----------------------------------
var sb = new StringBuilder(); var xmlReader = new XmlTextReader(getFilePath("XmlDocumentTest.xml")); while (xmlReader.Read()) { switch (xmlReader.NodeType) { case XmlNodeType.XmlDeclaration: case XmlNodeType.Element: case XmlNodeType.Comment: sb.AppendFormat("{0}: {1} = {2}", xmlReader.NodeType, xmlReader.Name, xmlReader.Value); sb.AppendLine(); break; case XmlNodeType.Text: sb.AppendFormat(" - Value: {0}", xmlReader.Value); sb.AppendLine(); break; } if (xmlReader.HasAttributes) { while (xmlReader.MoveToNextAttribute()) { sb.AppendFormat(" - Attribute: {0} = {1}", xmlReader.Name, xmlReader.Value); sb.AppendLine(); } } } xmlReader.Close(); txtLog.Text = sb.ToString();
Este código abre el archivo y luego realiza un ciclo simple, lee un elemento a la vez hasta que termine. Para cada nodo, se realiza una comprobación del NodeType, y la información del nodo se imprime.
XmlDeclaration: xml = version="1.0" encoding="utf-8" - Attribute: version = 1.0 - Attribute: encoding = utf-8 Element: MyRoot = Element: MyChild = - Attribute: ID = 1 Element: MyGrandChild = Element: MyGrandChild = Element: MyGrandChild = Element: MyChild = - Attribute: ID = 2 Element: MyGrandChild = Element: MyGrandChild = Element: MyGrandChild = Element: MyChild = - Attribute: ID = 3 Element: MyGrandChild = Element: MyGrandChild = Element: MyGrandChild = Element: MyChild = - Attribute: ID = 4 Element: MyGrandChild = Element: MyGrandChild = Element: MyGrandChild =
Al ver los resultados, muchas líneas terminan con un signo igual porque ninguno de los nodos contenidos de texto.
Resumen de la lección
■ La clase XmlDocument proporciona en memoria, lectura-escritura de acceso aleatorio a los nodos XML.
■ La clase XmlReader proporciona un streaming, sólo hacia delante, de acceso de sólo lectura a los nodos XML.
■ La clase XmlDocument es más fácil de usar, mientras que la clase XmlReader es más rápido.
■ La clase XmlDocument permite recuperar los nodos XML utilizando el nombre del elemento.
■ La clase XmlDocument permite recuperar los nodos XML mediante una consulta XPath.
No hay comentarios:
Publicar un comentario