Enreas
Advertisement

XML de trabajo[]

Como en el capítulo anterior, vamos a trabajar con el mismo documento XML durante éste. Se trata del siguiente:

<?xml version="1.0" encoding="iso-8859-15"?>
<pelicula titulo="Brazil" estreno="1985" minutos="142">
  <direccion>
    <director nombre="Terry" apellidos="Gilliam"/>
  </direccion>
  <produccion>
    <productor nombre="Patrick" apellidos="Cassavetti"/>
    <productor nombre="Arnon" apellidos="Milchan"/>
  </produccion>
  <guion>
    <guionista nombre="Terry" apellidos="Gilliam"/>
    <guionista nombre="Tom" apellidos="Stoppard"/>
    <guionista nombre="Charles" apellidos="McKeown"/>
  </guion>
  <reparto>
    <interprete nombre="Jonathan" apellidos="Pryce"
      papel="protagonista"/>
    <interprete nombre="Robert" apellidos="De Niro"
      papel="protagonista"/>
    <interprete nombre="Kim" apellidos="Greist"
      papel="protagonista"/>
    <interprete nombre="Michael" apellidos="Palin"
      papel="secundario"/>
    <interprete nombre="Ian" apellidos="Holm"
      papel="secundario"/>
    <interprete nombre="Bob" apellidos="Hoskins"
      papel="secundario"/>
  </reparto>
  <esloganes>
    <eslogan>
      Vuelos fantásticos.
      La pesadilla de la realidad.
      Ataques terroristas.
      Compras a media noche.
      Amor verdadero.
      Y fontanería creativa.
    </eslogan>
  </esloganes>
</pelicula>

Validación con DTD[]

Supongamos que queremos validar el documento XML con el que vamos a trabajar en este capítulo utilizando la siguiente DTD:

<!ELEMENT pelicula (direccion?,produccion?,guion?,reparto?,esloganes?)>
<!ATTLIST pelicula titulo CDATA #REQUIRED>
<!ATTLIST pelicula estreno CDATA #IMPLIED>
<!ATTLIST pelicula minutos CDATA #IMPLIED>

<!ELEMENT direccion (director+)>
<!ELEMENT director EMPTY>
<!ATTLIST director nombre CDATA #REQUIRED>
<!ATTLIST director apellidos CDATA #REQUIRED>

<!ELEMENT produccion (productor+)>
<!ELEMENT productor EMPTY>
<!ATTLIST productor nombre CDATA #REQUIRED>
<!ATTLIST productor apellidos CDATA #REQUIRED>

<!ELEMENT guion (guionista+)>
<!ELEMENT guionista EMPTY>
<!ATTLIST guionista nombre CDATA #REQUIRED>
<!ATTLIST guionista apellidos CDATA #REQUIRED>

<!ELEMENT reparto (interprete+)>
<!ELEMENT interprete EMPTY>
<!ATTLIST interprete nombre CDATA #REQUIRED>
<!ATTLIST interprete apellidos CDATA #REQUIRED>
<!ATTLIST interprete papel (protagonista | secundario) #REQUIRED>

<!ELEMENT esloganes (eslogan+)>
<!ELEMENT eslogan (#PCDATA)>

El siguiente programa realiza la validación del documento XML usando la DTD anterior:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlTextReader tr = 
        new XmlTextReader(sRuta + "Brazil.xml");
      XmlValidatingReader vr = 
        new XmlValidatingReader(tr);

      XmlDocument doc = new XmlDocument();
      doc.PreserveWhitespace = true;
      doc.Load(vr);
      Console.Write(doc.InnerXml);

    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

El documento XML debe ser modificado, incluyendo el siguiente código en la cabecera del mismo:

...
<!DOCTYPE pelicula SYSTEM "filmoteca.dtd">
...

Validación con esquemas[]

Como en la sección anterior, pero en lugar de una DTD trabajaremos con el siguiente esquema:

<?xml version="1.0"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
  <element name="pelicula">
    <complexType>
      <sequence>
        <element name="direccion">
          <complexType>
            <sequence>
              <element name="director" maxOccurs="unbounded">
                <complexType>
                  <attribute name="nombre" type="string" use="required"/>
                  <attribute name="apellidos" type="string" use="required"/>
                </complexType>
              </element>
            </sequence>
          </complexType>
        </element>
        <element name="produccion">
          <complexType>
            <sequence>
              <element name="productor" maxOccurs="unbounded">
                <complexType>
                  <attribute name="nombre" type="string" use="required"/>
                  <attribute name="apellidos" type="string" use="required"/>
                </complexType>
              </element>
            </sequence>
          </complexType>
        </element>
        <element name="guion">
          <complexType>
            <sequence>
              <element name="guionista" maxOccurs="unbounded">
                <complexType>
                  <attribute name="nombre" type="string" use="required"/>
                  <attribute name="apellidos" type="string" use="required"/>
                </complexType>
              </element>
            </sequence>
          </complexType>
        </element>
        <element name="reparto">
          <complexType>
            <sequence>
              <element name="interprete" maxOccurs="unbounded">
                <complexType>
                  <attribute name="nombre" type="string" use="required"/>
                  <attribute name="apellidos" type="string" use="required"/>
                  <attribute name="papel" type="string" use="required"/>
                </complexType>
              </element>
            </sequence>
          </complexType>
        </element>
        <element name="esloganes">
          <complexType>
            <sequence>
              <element name="eslogan" type="string" maxOccurs="unbounded"/>
            </sequence>
          </complexType>
        </element>
      </sequence>
      <attribute name="titulo" type="string" use="required"/>
      <attribute name="estreno" type="integer" use="optional"/>
      <attribute name="minutos" type="integer" use="optional"/>
    </complexType>
  </element>
</schema>

Puedes utilizar el mismo programa mostrado en la sección anterior. En este caso, el documento XML ha de ser modificado para que contenga el siguiente código en su cabecera:

...
<pelicula titulo="Brazil" estreno="1985" minutos="142"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="filmoteca.xsd">
...

Esto debe ir en lugar de:

...
<!DOCTYPE pelicula SYSTEM "filmoteca.dtd">
...

Creación de documentos[]

Se puede crear un documento XML desde cero, utilizando el lenguaje de programación de nuestra elección:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    try{

      string sXML = "";
      string sTitulo = "Brazil";
      
      sXML = "<pelicula titulo=\"" + sTitulo + "\"></pelicula>";
      
      XmlDocument doc = new XmlDocument();
      doc.LoadXml(sXML);
      
      Console.WriteLine(doc.OuterXml);
      
    }
    
    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Tras las creación, es posible trabajar con el documento recién creado, añadiendo nuevos elementos:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    try{

      string sXML = "";
      string sTitulo = "Brazil";
      
      sXML = "<pelicula titulo=\"" + sTitulo + "\"></pelicula>";
      
      XmlDocument doc = new XmlDocument();
      doc.LoadXml(sXML);

      Console.WriteLine("Antes: " + doc.OuterXml);

      XmlNode nodo;
      nodo = doc.CreateNode(XmlNodeType.Element,"direccion","");
      doc.DocumentElement.AppendChild(nodo);
      
      Console.WriteLine("Después: " + doc.OuterXml);
      
    }
    
    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Inserción de atributos[]

Una vez creado el documento XML utilizando DOM, es posible realizar muchas operaciones con él. Por ejemplo, se pueden añadir atributos a documentos ya existentes. El siguiente programa sirve para tal fin:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    try{

      XmlDocument doc = new XmlDocument();

      XmlDeclaration dec;
      dec = doc.CreateXmlDeclaration("1.0","","");
      doc.InsertBefore(dec,doc.DocumentElement);

      XmlWhitespace espacio;
      espacio = doc.CreateWhitespace("\n");
      doc.InsertAfter(espacio,dec);

      XmlElement elemento;

      elemento = doc.CreateElement("pelicula");
      
      XmlAttribute atr;
      atr = doc.CreateAttribute("titulo");
      atr.Value = "Brazil";
      
      elemento.SetAttributeNode(atr);

      doc.AppendChild(elemento);

      Console.WriteLine(doc.OuterXml);
    
    }
    
    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Con lo visto hasta ahora podemos crear de la nada el documento de trabajo de este capítulo:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    try{

      XmlDocument doc = new XmlDocument();

      XmlElement elemento;
      XmlAttribute atr;

      // Creación del elemento raíz.      
      elemento = doc.CreateElement("pelicula");

      atr = doc.CreateAttribute("titulo");
      atr.Value = "Brazil";
      elemento.SetAttributeNode(atr);

      atr = doc.CreateAttribute("estreno");
      atr.Value = "1985";
      elemento.SetAttributeNode(atr);

      atr = doc.CreateAttribute("minutos");
      atr.Value = "142";
      elemento.SetAttributeNode(atr);

      doc.AppendChild(elemento);

      // Creación de los eslóganes.      
      elemento = doc.CreateElement("esloganes");
      doc.DocumentElement.AppendChild(elemento);

      // Creación de un eslogan.      
      elemento = doc.CreateElement("eslogan");
      elemento.InnerText = 
        "Vuelos fantásticos. " +
        "La pesadilla de la realidad. " +
        "Ataques terroristas. " +
        "Compras a media noche. " +
        "Amor verdadero. " +
        "Y fontanería creativa.";
      
      doc.SelectSingleNode("/pelicula/esloganes").AppendChild(elemento);
      
      Console.WriteLine(doc.OuterXml);
    
    }
    
    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Queda como ejercicio para el lector crear el resto de elementos: produccion, guion, reparto, así como todos sus nodos hijos.

Inserción de la cabecera[]

Al documento que acabamos de crear le falta aún algún detalle para estar completo. Por ejemplo, la cabecera. La podemos insertar así:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlDocument doc = new XmlDocument();

      XmlDeclaration dec;
      dec = doc.CreateXmlDeclaration("1.0","","");
      doc.InsertBefore(dec,doc.DocumentElement);

      XmlElement elemento;
      elemento = doc.CreateElement("pelicula");
      
      XmlAttribute atr;
      atr = doc.CreateAttribute("titulo");
      atr.Value = "Brazil";
      
      elemento.SetAttributeNode(atr);

      doc.AppendChild(elemento);
      
      Console.WriteLine(doc.OuterXml);
      
    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Directivas DOCTYPE[]

La inserción de directivas DOCTYPE es muy similar a la inserción de cabeceras vista en la sección anterior:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlDocument doc = new XmlDocument();

      XmlDeclaration dec;
      dec = doc.CreateXmlDeclaration("1.0","","");
      doc.InsertBefore(dec,doc.DocumentElement);

      XmlDocumentType doctype;
      doctype = doc.CreateDocumentType("pelicula", null, null, "<!ELEMENT pelicula ANY>");
      doc.AppendChild(doctype);

      XmlElement elemento;
      elemento = doc.CreateElement("pelicula");
      
      XmlAttribute atr;
      atr = doc.CreateAttribute("titulo");
      atr.Value = "Brazil";
      
      elemento.SetAttributeNode(atr);

      doc.AppendChild(elemento);
      
      Console.WriteLine(doc.OuterXml);
      
    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Modificación de elementos[]

Si lo deseas, es posible modificar el contenido de un determinado elemento:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlDocument doc = new XmlDocument();

      doc.PreserveWhitespace = true;
      doc.Load(sRuta + "brazil.xml");
      
      XmlNode eslogan;
      eslogan = doc.SelectSingleNode("/pelicula/esloganes/eslogan");
      eslogan.InnerText = "No hay eslogan";
      
      Console.WriteLine(doc.OuterXml);
      
    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

De forma similar, se puede modificar el valor de un atributo:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlDocument doc = new XmlDocument();

      doc.PreserveWhitespace = true;
      doc.Load(sRuta + "brazil.xml");
      
      XmlNode pelicula;
      pelicula = doc.SelectSingleNode("/pelicula");
      
      XmlAttributesCollection atrs;
      atrs = pelicula.Attributes;
      atrs("minutos").Value ="131";
      
      Console.WriteLine(doc.OuterXml);
      
    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Borrado de elementos[]

Es posible eliminar el elemento esloganes con el siguiente programa:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlDocument doc = new XmlDocument();

      doc.PreserveWhitespace = true;
      doc.Load(sRuta + "brazil.xml");
      
      XmlNode nodo;
      nodo = doc.SelectSingleNode("/pelicula/esloganes");
      doc.DocumentElement.RemoveChild(nodo);
      
      Console.WriteLine(doc.OuterXml);
      
    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

En lugar de eliminar todos los eslóganes, es posible limitarse a uno de ellos:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlDocument doc = new XmlDocument();

      doc.PreserveWhitespace = true;
      doc.Load(sRuta + "brazil.xml");
      
      XmlNode esloganes;
      esloganes = doc.SelectSingleNode("/pelicula/esloganes");

      XmlNode eslogan;
      eslogan = doc.SelectSingleNode("/pelicula/esloganes/eslogan");
      esloganes.RemoveChild(eslogan);
      
      Console.WriteLine(doc.OuterXml);
      
    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

El borrado también puede limitarse a un atributo:

using System;
using System.Xml;

class MainClass
{
  public static void Main(string[] args)
  {

    string sRuta = "C:\\XML\\";
    // string sRuta = "/home/enreas/andy/XML/";

    try{

      XmlDocument doc = new XmlDocument();

      doc.PreserveWhitespace = true;
      doc.Load(sRuta + "brazil.xml");
      
      XmlNode nodo;
      nodo = doc.SelectSingleNode("pelicula");

      XmlAttributeColletion atrs;
      atrs = nodo.Attributes;
      atrs.Remove(atrs["minutos"]);
      
      Console.WriteLine(doc.OuterXml);
      
    }

    catch(Exception e){

      Console.WriteLine("Error: '{0}'", e);

    }

  }
}

Almacenamiento del documento[]

Cuando terminemos de realizar las operaciones deseadas con el documento XML, podemos guardar los cambios. Añada el siguiente fragmento de código al bloque try, tras las operaciones que haya realizado sobre el documento:

...
XmlTextWriter escriba =
  newXmlTextWriter(sRuta + "brazil2.xml", null);
escriba.Formatting = Formatting.Indented;
doc.Save(escriba);
...
Advertisement