Преобразование XML файла в CSV файл с помощью java

Мне нужна помощь в понимании шагов, связанных с преобразованием файла XML в CSV файл с использованием java. Вот пример 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>

и вот результат CSV файла.

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

Я думал использовать DOM-парсер для чтения XML файла. Проблема, с которой я сталкиваюсь, заключается в том, что мне нужно будет указать конкретные элементы в код по имени, но я хочу, чтобы он мог анализировать его, не делая этого.

Есть ли в java инструменты или библиотеки, которые могли бы помочь мне в этом.

Если у меня есть XML файл этого формата ниже и вы хотите добавить значение InitgPty в ту же строку с MSgId (примечание Pls: InitgPty находится на следующем уровне тега, поэтому он печатает значение в следующей строке)

<?xml version="1.0"?>
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>XYZ07/ABC</MsgId>
<NbOfTxs>100000</NbOfTxs>
<InitgPty>
<Nm>XYZ</Nm>
</InitgPty>

Ответ 1

здесь рабочий пример, data.xml содержит ваши данные:

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,'&#xA;')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

выход:

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

Ответ 3

Лучше всего использовать XSLT для "преобразования" XML в CSV. Есть некоторые Q/As, поэтому (например, здесь), которые расскажут, как это сделать. Ключ должен предоставить схему для исходных данных, чтобы процесс преобразования XSLT знал, как читать его, чтобы он мог правильно форматировать результаты.

Затем вы можете использовать Xalan для ввода XML, чтения XSLT и вывода результатов.

Ответ 4

Ответ уже предоставлен Pedantic (с использованием DOM-подобного подхода {Document Object Model}) и Jono (с подобным SAX-подходом на этот раз) в январе.

Я считаю, что оба метода хорошо работают для небольших файлов, но последнее лучше работает с большими файлами XML. Вы не указали фактический размер ваших XML файлов, но вы должны учитывать это.

Независимо от того, какой метод используется, конкретная программа (которая будет определять специальные теги, адаптированные к вашему локальному XML), будет легче писать, но не будет работать без адаптации кода для другого XML-вкуса, в то время как более общая программа будет сложнее разработать но будет работать для всех файлов XML. Вы сказали, что хотите разбирать файл без указания имен конкретных элементов, поэтому я предполагаю, что общий подход - это то, что вы предпочитаете, и я согласен с этим, но учтите, что это проще сказать, чем сделать. В самом деле, у меня была такая же проблема и в январе, подразумевая на этот раз большой XML файл ( → 100Mo), и я был удивлен, что до сих пор ничего не было доступно через Интернет. Превращение разочарования в что-то лучшее всегда хорошо, поэтому я решил решить эту конкретную проблему самым общим образом сам с особой заботой о большом-XML файле-проблеме.

Вам может быть интересно узнать, что общая библиотека Java, которую я написал, которая теперь опубликована как бесплатное программное обеспечение, преобразует ваш XML файл в CSV так, как вы ожидали (в режиме -x -u (см. дополнительную документацию информация}).

Итак, ответ на последнюю часть вашего вопроса: да, есть хотя бы одна библиотека, которая поможет вам достичь своей цели, моей, которая называется "XML2CSV-Generic-Converter". Конечно, могут быть и другие, и, конечно же, лучше, но я не мог выбрать какой-либо достойный (свободный) сам.

Я не буду указывать здесь какую-либо ссылку, чтобы соответствовать замечательному замечанию Питера Фоти, но если вы закроете "XML2CSV-Generic-Converter" в своей любимой поисковой системе, вы должны легко ее найти.

Ответ 5

ваш файл выглядит очень плоским и простым. Вам не обязательно нужен синтаксический анализатор XML для его преобразования. Просто проанализируйте его с помощью LineNumberReader.readLine() и используйте regexp для извлечения определенных полей.

Другой вариант - использовать StAX, потоковый API для обработки XML. Это довольно просто, и вам не нужно загружать весь документ в ОЗУ.