Archivos Mensuales: noviembre 2009

Etiquetas en los códigos de Digi.Tab

El formato del nuevo Digi.tab.xml que se introdujo en Digi a partir de la versión 2007 es muy flexible ya que está basado en el standard XML, lo que permite añadir campos sin romper la compatibilidad.

En este ejercicio, vamos a modificar un Digi.tab.xml automáticamente para añadirle un concepto que tiene la versión de Digi para MGCP y que tiene la futura version Digi3D 2011.

En la nuev versión de Digi, los códigos pueden tener asociadas etiquetas. Cada código puede tener un número ilimitado de etiquetas, que no son más que nombres separados por comas.

Así pues, si un determinado código tiene el siguiente valor en el campo etiqueta: “Edificios,Edificios en construcción,1:1000” dicho código tendrá tres etiquetas:

a) Edificios
b) Edificios en construcción
c) 1:1000

¿Para que sirven las etiquetas?

Pues básicamente para agrupar códigos.

Si tenemos 10 códigos con la etiqueta “Edificios”, podemos ejecutar cualquier orden que trabaje con etiquetas para trabajar con todos esos códigos a la vez.

Ej: En la versión 2011 de DigiNG, podemos ejecutar la orden: BORRA_COD=#Edificios L
para borrar todas las líneas cuyos códigos tengan la etiqueta “Edificios”.

Cuando desarrollamos el módulo de MGCP para DigiNG, no existía el concepto de etiquetas, sin embargo, era necesario agrupar de alguna manera códigos para hacer topologías. Esto se hizo en un archivo nuevo que denominamos mgcp.xml.

Aquí tenemos un recorte del archivo mgcp.xml:

<?xml version="1.0" ?>
<menuMGCP>

  <bintop name="Terreno inundable">
    BBH090
    CBH090
  </bintop>

  <bintop name="Landcover Area Features">
      L1
      CZD020
      CZD020
      CBH030
      CBH030
      CBH020
      CBH130
      CBH080
      CBH140
      CBA040
      CDB170
  </bintop>

  <bintop name="Isla">
    BBA030
    CBA030
  </bintop>

  <bintop name="Aeródromo">
    BGB005
    CGB005
  </bintop>

</menuMGCP>

La idea es que se pueda continuar el proyecto MGCP con Digi3D 2011, y lógicamente sin el archivo mgcp.xml (que Digi3D 2011 no sabe interpretar). Tenemos que añadir el contenido del archivo mgcp.xml como etiquetas dentro de un Digi.tab.xml existente.

A continuación tienes el código fuente de una pequeña aplicación en C# que va a hacer el proceso automáticamente.

Va a cargar el archivo mgcp.xml con los grupos de códigos (en la etiqueta “bintop”), luego va a cargar un digi.tab y va a ir añadiéndo a cada código las etiquetas que le correspondan.

Por último, va a guardar el digi.tab modificado con otro nombre.

Como es una aplicación que se va a ejecutar una única vez, no he dedicado tiempo a comprobar si un determinado código ya tenía una etiqueta o no, eso os lo dejo como tarea de programación.

Es un ejemplo interesante, ya que utiliza objetos Xml de .NET para cargar y modificar los archivos de tablas, utiliza XPath para realizar búsquedas en los dos archivos xml y además utiliza Linq to Objects para separar los códigos de cada tabla en el archivo .xml original en líneas.

Aquí está el código:

using System;
using System.Linq;
using System.Xml;
using System.Xml.XPath;

namespace AnadeEtiquetas
{
    class Program
    {
        static void Main(string[] args)
        {

            XmlDocument digiTab = new XmlDocument();
            digiTab.Load("digi.tab.xml");
            XPathNavigator navegadorDigiTab = digiTab.CreateNavigator();

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ProhibitDtd = false;

            using( XmlReader readerMGCP = XmlReader.Create("mgcp.xml", settings) )
            {
                XPathDocument mgcpXML = new XPathDocument(readerMGCP);

                XPathNavigator navegadorMGCP = mgcpXML.CreateNavigator();

                foreach(XPathNavigator tablaDeCodigos in navegadorMGCP.Select("/menuMGCP/bintop") )
                {
                    string nombreTabla = tablaDeCodigos.GetAttribute("name", "");

                    Console.WriteLine("Insertando la tabla {0} en el digi.tab", nombreTabla);

                    var listaDeCodigos = from código in tablaDeCodigos.Value.Split('n')
                                let códigoRecortado = código.Trim()
                                where códigoRecortado.Length > 0
                                select códigoRecortado;

                    foreach (string código in listaDeCodigos)
                    {
                        XPathNodeIterator nodosDigiTab =
                            navegadorDigiTab.Select("/digitab/codes/code[@name="" + código + ""]");

                        foreach (XPathNavigator nodo in nodosDigiTab)
                        {
                            if (nodo.MoveToAttribute("tags", ""))
                                nodo.SetValue(nodo.Value + "," + tablaDeCodigos.GetAttribute("name", "").ToString());
                            else
                                nodo.CreateAttribute("", "tags", "", tablaDeCodigos.GetAttribute("name", "").ToString());
                        }
                    }
                }
            }

            navegadorDigiTab.MoveToRoot();
            using (XmlWriter writter = XmlWriter.Create("digitabmodificado.tab.xml"))
            {
                writter.WriteNode(navegadorDigiTab, false);
                writter.Flush();
            }
        }
    }
}