El siguiente ejemplo al igual que el anterior de SAX esta basado en el parser Xerces 2.0, sin embargo, también se hace uso de las librerías JAXP por lo que puede ser ejecutado en otro parser Java sin complicaciones.
Dentro de este programa se define una función llamada imprimirnodos
, esta función actúa de una forma recursiva, esto significa que dentro de la misma función vuelve a ser llamada, lo anterior va en acorde con el comportamiento de árbol en DOM.
package com.osmosislatina.xml.dom; // Librerías de I/O import java.io.*; // Librerías de DOM import org.w3c.dom.*; // Clases JAXP import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; // Clases SAX import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class ArbolDOM { // // Programa Principal // // Variables static Document document; protected static PrintWriter out; /** Inicio Programa Principal */ public static void main (String args []) { // Revisar que exista un archivo de entrada if (args.length != 1) { System.err.println ("Debe indicar un archivo XML para ser procesado"); System.exit (1); } // Crear la fabrica utilizada para DOM DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { // Generar el Stream para enviar a Pantalla out = new PrintWriter (System.out); // Procesar archivo DocumentBuilder builder = factory.newDocumentBuilder(); // Definir un ErrorHandler (Estilo SAX) para atrapar Errores. builder.setErrorHandler( // Definir Clase Interna para Control de Errores new org.xml.sax.ErrorHandler() { // Ignorar Errores Fatales public void fatalError(SAXParseException exception) throws SAXException { } // Tratar errores de Validacion public void error(SAXParseException e) throws SAXParseException { throw e; } // Tratar avisos a Consola public void warning(SAXParseException err) throws SAXParseException { System.out.println("** Warning" + ", line " + err.getLineNumber() + ", uri " + err.getSystemId()); System.out.println(" " + err.getMessage()); } } ); // Iniciar Proceso de "Parse" document = builder.parse( new File(args[0]) ); ArbolDOM writer = new ArbolDOM(); writer.imprimirNodos(document); } catch (ParserConfigurationException pexc) { pexc.printStackTrace(); } catch (Exception exc) { System.out.println(" " + exc.getMessage() ); } } |
A continuación se describe el método de impresión y un método auxiliar utilizado para ordenar los atributos de cada elemento.
public void imprimirNodos(Node node) { // Si ya no existen nodos por Imprimir salir..... if ( node == null ) { return; } /** Investigar el Tipo de Nodo */ int type = node.getNodeType(); /** En base al Tipo de Nodo ejecutar */ switch ( type ) { // Imprimir Documento case Node.DOCUMENT_NODE: { NodeList children = node.getChildNodes(); for ( int iChild = 0; iChild < children.getLength(); iChild++ ) { imprimirNodos(children.item(iChild)); } out.flush(); break; } // Imprimir elementos con atributos case Node.ELEMENT_NODE: { out.print('<'); out.print(node.getNodeName()); Attr attrs[] = sortAttributes(node.getAttributes()); for ( int i = 0; i < attrs.length; i++ ) { Attr attr = attrs[i]; out.print(' '); out.print(attr.getNodeName()); out.print("=\""); out.print(attr.getNodeValue()); out.print('"'); } out.print('>'); NodeList children = node.getChildNodes(); if ( children != null ) { int len = children.getLength(); for ( int i = 0; i < len; i++ ) { imprimirNodos(children.item(i)); } } break; } // Imprimir Texto case Node.TEXT_NODE: { out.print(node.getNodeValue()); break; } // Imprimir Nodos con Instrucciones de Proceso case Node.PROCESSING_INSTRUCTION_NODE: { out.print("<?"); out.print(node.getNodeName()); String data = node.getNodeValue(); if ( data != null && data.length() > 0 ) { out.print(' '); out.print(data); } out.println("?>"); break; } // Imprimir Texto de Elementos CDATA case Node.CDATA_SECTION_NODE: { out.print(node.getNodeValue()); break; } } // Termina Switch // En caso de ser nodo de Elemento cerrar Tag en Pantalla if ( type == Node.ELEMENT_NODE ) { out.print("</"); out.print(node.getNodeName()); out.print('>'); } // Enviar a Pantalla Buffer out.flush(); } // Termina Impresion de Nodos /** Funcion utilizada para Ordenar Atributos de Elementos */ protected Attr[] sortAttributes(NamedNodeMap attrs) { int len = (attrs != null) ? attrs.getLength() : 0; Attr array[] = new Attr[len]; for ( int i = 0; i < len; i++ ) { array[i] = (Attr)attrs.item(i); } for ( int i = 0; i < len - 1; i++ ) { String name = array[i].getNodeName(); int index = i; for ( int j = i + 1; j < len; j++ ) { String curName = array[j].getNodeName(); if ( curName.compareTo(name) < 0 ) { name = curName; index = j; } } if ( index != i ) { Attr temp = array[i]; array[i] = array[index]; array[index] = temp; } } return(array); } // Terminar ordenar de Atributos } |
template
, XPath, Condicionales y Ciclos en XSL.