使用 java 将 XML 文件转换为 CSV 文件

Posted

技术标签:

【中文标题】使用 java 将 XML 文件转换为 CSV 文件【英文标题】:Convert an XML file to CSV file using java 【发布时间】:2014-02-20 05:54:56 【问题描述】:

我需要帮助了解所涉及的步骤。 这是一个 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 相同的行中(请注意: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

【讨论】:

我试图解决此代码以仅构建一个 csv,但不能。关于我如何做到这一点的任何提示?我有 100 多个 XML 文件需要转换为单个 csv 文件。 我试过了,但我只得到了 cloumns 的名称......我应该改变什么? 那么style.xsl文件,如果没有,需要手动创建吗?如果您不想要 CSV 中的标题会怎样?怎么可能做到? @iot-user,编辑 style.xsl 应该可以得到你想要的。删除其中的标题行。 如何获取子节点数据到 csv 示例:schemas.microsoft.com/ado/2007/08/dataservices/metadata"> 0z342bvff world_catalonCatalon【参考方案2】:

三个步骤:

    将 XML 文件解析为 java XML library 对象。 Retrieve relevant data 来自每一行的对象。 Write the results to a text file using native java functions,以 *.csv 扩展名保存。

【讨论】:

【参考方案3】:

最好的办法是使用XSLT 将XML“转换”为CSV。有一些问答(如here)涵盖了如何做到这一点。关键是为您的源数据提供一个模式,以便 XSLT 转换过程知道如何读取它,以便正确格式化结果。

然后您可以使用Xalan 输入XML,读取XSLT 并输出您的结果。

【讨论】:

我想我会这样做。【参考方案4】:

Pedantic(使用类似 DOM 的方法 Document Object Model)和 Jono(这次使用类似 SAX 的方法)已经在一月份提供了答案。

我认为这两种方法都适用于小文件,但后者适用于大 XML 文件。您没有提及 XML 文件的实际大小,但您应该考虑到这一点。

无论使用什么方法,一个特定的程序(它将检测为您的本地 XML 量身定制的特殊标签)将更容易编写,但如果没有针对另一种 XML 风格的代码改编将无法工作,而更通用的程序将更难设计但适用于所有 XML 文件。 您说您希望能够在不指定特定元素名称的情况下解析文件,所以我想通用方法是您喜欢的,我同意这一点,但请注意,说起来容易做起来难。 事实上,我在一月份也遇到了同样的问题,这意味着这次是一个很大的 XML 文件 (>>100Mo),我很惊讶到目前为止在 Internet 上没有可用的东西。 将挫败感转化为更好的事情总是一件好事,所以我决定自己以最通用的方式处理这个特定问题,特别关注 big-XML-file-issue。 p>

您可能有兴趣知道我编写的通用 Java 库现在作为免费软件发布,它以您期望的方式将您的 XML 文件转换为 CSV(在 -x -u 模式下请参阅文档以获取更多信息)信息)。

所以你的问题的最后一部分的答案是:是的,至少有一个库可以帮助你实现你的目标,我的,它被命名为“XML2CSV-Generic-Converter”。 当然可能还有其他的,当然还有更好的,但我自己挑不出任何像样的(免费)。

我不会在此处提供任何链接以符合 Peter Foti 的明智评论 - 但如果您在您最喜欢的搜索引擎中键入“XML2CSV-Generic-Converter”,您应该很容易找到它。

【讨论】:

【参考方案5】:

您的文件看起来非常简单。您不一定需要 XML 解析器来转换它。 只需使用LineNumberReader.readLine() 解析它并使用regexp 来提取特定字段。

另一种选择是使用StAX,这是一种用于 XML 处理的流式 API。这非常简单,您不需要将整个文档加载到 RAM 中。

【讨论】:

【参考方案6】:

http://beanio.org/2.1/docs/reference/index.html#Records 这是一种快速而强大的解决方案。

【讨论】:

以上是关于使用 java 将 XML 文件转换为 CSV 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 XSLT 将 CSV 文件转换为 XML

使用JAXB在JAVA中将CSV文件转换为层次结构XML

将 CSV 文件转换为 XML

在python中使用argparse将csv转换为xml

使用 Python 将 XML 转换为 CSV

有没有办法使用 KnockoutJS 将 XML 文件转换为 CSV?