scanner - read.csv java
Convierta un archivo XML a un archivo CSV usando Java (5)
Necesito ayuda para entender los pasos necesarios para convertir un archivo XML en un archivo CSV utilizando java. Aquí hay un ejemplo de un archivo XML
<?xml version="1.0"?>
<Sites>
<Site id="101" name="NY-01" location="New York">
<Hosts>
<Host id="1001">
<Host_Name>srv001001</Host_Name>
<IP_address>10.1.2.3</IP_address>
<OS>Windows</OS>
<Load_avg_1min>1.3</Load_avg_1min>
<Load_avg_5min>2.5</Load_avg_5min>
<Load_avg_15min>1.2</Load_avg_15min>
</Host>
<Host id="1002">
<Host_Name>srv001002</Host_Name>
<IP_address>10.1.2.4</IP_address>
<OS>Linux</OS>
<Load_avg_1min>1.4</Load_avg_1min>
<Load_avg_5min>2.5</Load_avg_5min>
<Load_avg_15min>1.2</Load_avg_15min>
</Host>
<Host id="1003">
<Host_Name>srv001003</Host_Name>
<IP_address>10.1.2.5</IP_address>
<OS>Linux</OS>
<Load_avg_1min>3.3</Load_avg_1min>
<Load_avg_5min>1.6</Load_avg_5min>
<Load_avg_15min>1.8</Load_avg_15min>
</Host>
<Host id="1004">
<Host_Name>srv001004</Host_Name>
<IP_address>10.1.2.6</IP_address>
<OS>Linux</OS>
<Load_avg_1min>2.3</Load_avg_1min>
<Load_avg_5min>4.5</Load_avg_5min>
<Load_avg_15min>4.2</Load_avg_15min>
</Host>
</Hosts>
</Site>
</Sites>
y aquí está el archivo CSV resultante.
site_id, site_name, site_location, host_id, host_name, ip_address, operative_system, load_avg_1min, load_avg_5min, load_avg_15min
101, NY-01, New York, 1001, srv001001, 10.1.2.3, Windows, 1.3, 2.5, 1.2
101, NY-01, New York, 1002, srv001002, 10.1.2.4, Linux, 1.4, 2.5, 1.2
101, NY-01, New York, 1003, srv001003, 10.1.2.5, Linux, 3.3, 1.6, 1.8
101, NY-01, New York, 1004, srv001004, 10.1.2.6, Linux, 2.3, 4.5, 4.2
Estaba pensando en usar un analizador DOM para leer el archivo xml. El problema que tengo con eso es que necesitaría especificar elementos específicos para codificar por nombre, pero quiero que pueda analizarlo sin hacer eso.
¿Hay alguna herramienta o biblioteca en Java que pueda ayudarme a lograr esto?
Si tengo un archivo XML de este formato a continuación y deseo agregar el valor de InitgPty en la misma fila con MSgId (nota Pls: InitgPty está en el siguiente nivel de etiqueta, por lo que imprime el valor en la siguiente fila)
<?xml version="1.0"?>
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>XYZ07/ABC</MsgId>
<NbOfTxs>100000</NbOfTxs>
<InitgPty>
<Nm>XYZ</Nm>
</InitgPty>
Aquí hay un ejemplo de trabajo, data.xml
tiene sus datos:
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
class Xml2Csv {
public static void main(String args[]) throws Exception {
File stylesheet = new File("src/main/resources/style.xsl");
File xmlSource = new File("src/main/resources/data.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlSource);
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(stylesource);
Source source = new DOMSource(document);
Result outputTarget = new StreamResult(new File("/tmp/x.csv"));
transformer.transform(source, outputTarget);
}
}
style.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
Host_Name,IP_address,OS,Load_avg_1min,Load_avg_5min,Load_avg_15min
<xsl:for-each select="//Host">
<xsl:value-of select="concat(Host_Name,'','',IP_address,'','',OS,Load_avg_1min,'','',Load_avg_5min,'','',Load_avg_15min,''
'')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
salida:
Host_Name,IP_address,OS,Load_avg_1min,Load_avg_5min,Load_avg_15min
srv001001,10.1.2.3,Windows1.3,2.5,1.2
srv001002,10.1.2.4,Linux1.4,2.5,1.2
srv001003,10.1.2.5,Linux3.3,1.6,1.8
srv001004,10.1.2.6,Linux2.3,4.5,4.2
su archivo se ve muy simple y plano. No necesita necesariamente un analizador XML para convertirlo. Solo LineNumberReader.readLine()
con LineNumberReader.readLine()
y usa regexp
para extraer campos específicos.
Otra opción es usar StAX
, una API de transmisión para procesamiento XML. Es bastante simple y no necesita cargar todo el documento en la RAM.
La respuesta ya ha sido proporcionada por Pedantic (usando el enfoque tipo DOM {Document Object Model}) y Jono (con el enfoque similar a SAX esta vez) en enero.
Mi opinión es que ambos métodos funcionan bien para archivos pequeños, pero este último funciona mejor con archivos XML grandes. No mencionó el tamaño real de sus archivos XML, pero debe tener esto en cuenta.
Independientemente del método utilizado, un programa específico (que detectaría etiquetas especiales adaptadas a su XML local) será más fácil de escribir, pero no funcionará sin adaptaciones de código para otro sabor XML, mientras que un programa más genérico será más difícil de diseñar, pero funcionará para todos los archivos XML. Dijiste que querías poder analizar un archivo sin especificar nombres de elementos específicos, así que supongo que el enfoque genérico es el que prefieres, y estoy de acuerdo con eso, pero ten en cuenta que es más fácil decirlo que hacerlo. De hecho, tuve el mismo problema en enero también, lo que implica esta vez un gran archivo XML (>> 100Mo) y me sorprendió que hasta ahora no haya nada disponible en Internet. Convertir la frustración en algo mejor siempre es algo bueno, así que decidí abordar ese problema específico de la manera más genérica por mí mismo, con una preocupación especial por el gran problema del archivo XML .
Puede que le interese saber que la biblioteca genérica de Java que escribí, que ahora se publica como software libre, convirtió su archivo XML en CSV de la forma esperada (en modo -x-u {consulte la documentación para obtener más información}) .
Entonces la respuesta a la última parte de su pregunta es: sí, hay al menos una biblioteca que lo ayudará a lograr su objetivo, el mío, que se llama "XML2CSV-Generic-Converter". Puede haber otros, por supuesto, y mejores, sin duda, pero no pude elegir ninguno decente (libre) por mi cuenta.
No proporcionaré ningún enlace aquí para cumplir con la juiciosa observación de Peter Foti, pero si introduce "XML2CSV-Generic-Converter" en su motor de búsqueda favorito, debería encontrarlo fácilmente.
Lo mejor es usar XSLT para "transformar" el XML a CSV. Hay algunas preguntas y respuestas sobre cómo (como aquí ) que cubren cómo hacer esto. La clave es proporcionar un esquema para sus datos de origen para que el proceso de transformación XSLT sepa cómo leerlo para que pueda formatear adecuadamente los resultados.
Luego puede usar Xalan para ingresar el XML, leer el XSLT y dar salida a sus resultados.
Tres pasos:
- Analice el archivo XML en un objeto de biblioteca XML java.
- Recupere datos relevantes del objeto para cada fila.
- Escriba los resultados en un archivo de texto usando funciones nativas de Java , guardando con la extensión * .csv.