将具有多个 for-each 案例的 XML 转换为 CSV

Convert XML having multiple for-each case to CSV

我编写了一个 Java 程序,可以将 XML 转换为 CSV。但目前它只转换部分。

FileUtils.writeByteArrayToFile(new File("src/main/resources/excel/Data.xml"), inputFile);
          File stylesheet = new File("src/main/resources/excel/Data.xsl");
          File xmlSource = new File("src/main/resources/excel/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);
          String path = "src/main/resources/excel/validatedXmlToCSV.csv";
          Result outputTarget = new StreamResult(new File(path));
          transformer.transform(source, outputTarget);

这是采用 XML 和 XSL 并将其转换为 CSV 的 Java 代码。

XML 我试图将其转换为 CSV 的文件是:

<root>
  <row>
    <TECHNICIANID>AA5263</TECHNICIANID>
    <CUID>AA5263</CUID>
    <TURFS>
      <TURF>
        <AREANAME>CA_MILPITAS_ABEL_A</AREANAME>
        <DEFAULT>Y</DEFAULT>
        <ALTERNATE>Y</ALTERNATE>
      </TURF>
      <TURF>
        <AREANAME>CA_SNJS_WHITE_RD_A</AREANAME>
        <DEFAULT>Y</DEFAULT>
        <ALTERNATE>Y</ALTERNATE>
      </TURF>
    </TURFS>
  </row>
  <row>
    <TECHNICIANID>AC1964</TECHNICIANID>
    <CUID>AC1964</CUID>
    <TURFS>
      <TURF>
        <AREANAME>CA_MILPITAS_ABEL_A</AREANAME>
        <DEFAULT>Y</DEFAULT>
        <ALTERNATE>Y</ALTERNATE>
      </TURF>
      <TURF>
        <AREANAME>CA_SNJS_WHITE_RD_A</AREANAME>
        <DEFAULT>Y</DEFAULT>
        <ALTERNATE>Y</ALTERNATE>
      </TURF>
    </TURFS>
  </row>
</root>

让我向您展示我是如何编写无法正常工作的 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="/">TECHNICIANID,CUID,TURFS/TURF/0/AREANAME,TURFS/TURF/0/DEFAULT,TURFS/TURF/0/ALTERNATE,TURFS/TURF/1/AREANAME,TURFS/TURF/1/DEFAULT,TURFS/TURF/1/ALTERNATE
<xsl:for-each select="/root/row">
<xsl:value-of select="concat(TECHNICIANID,',',CUID,'
&#xA;')"/>
<xsl:for-each select="/TURFS/TURF">
<xsl:value-of select="concat(AREANAME,',',DEAFAULT,',',ALTERNATE,',
&#xA;')"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

目前在转换时仅打印行 TECHNICIANID 和 CUID。其他不打印。

预期输出:

TECHNICIANID,CUID,TURFS/TURF/0/AREANAME,TURFS/TURF/0/DEFAULT,TURFS/TURF/0/ALTERNATE,TURFS/TURF/1/AREANAME,TURFS/TURF/1/DEFAULT,TURFS/TURF/1/ALTERNATE
AA5263,AA5263,CA_MILPITAS_ABEL_A,Y,Y,CA_SNJS_WHITE_RD_A,Y,Y
AC1964,AC1964,CA_MILPITAS_ABEL_A,Y,Y,CA_SNJS_WHITE_RD_A,Y,Y

我猜里面的<xsl:for-each select="/TURFS/TURF">应该是<xsl:for-each select="TURFS/TURF">concat(AREANAME,',',DEAFAULT 应该是 concat(AREANAME,',',DEFAULT.

我相信你可以简单地做到:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:template match="/root">
    <!-- header -->
    <xsl:text>TECHNICIANID,CUID,TURFS/TURF/0/AREANAME,TURFS/TURF/0/DEFAULT,TURFS/TURF/0/ALTERNATE,TURFS/TURF/1/AREANAME,TURFS/TURF/1/DEFAULT,TURFS/TURF/1/ALTERNATE&#10;</xsl:text>
    <!-- data -->
    <xsl:for-each select="row">
        <xsl:value-of select=".//*[not(*)]" separator=","/>
        <xsl:text>&#10;</xsl:text>  
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

演示:https://xsltfiddle.liberty-development.net/bF2MmXG/1


如果您想明确选择值,则更改:

<xsl:value-of select=".//*[not(*)]" separator=","/>

至:

<xsl:value-of select="TECHNICIANID, CUID, TURFS/TURF[1]/(AREANAME, DEFAULT, TALTERNATE), TURFS/TURF[2]/(AREANAME, DEFAULT, TALTERNATE)" separator=","/>

您的问题涉及从多级 XML 文件中提取数据并将其转换为 CSV 文件。 Java 代码很复杂。

使用SPL,open-source Java包进行转换很方便。你只需要几行代码:

A
1 =xml(file("Data.xml").read(),"root/row").conj(TECHNICIANID|CUID|TURFS.TURF.conj(~.array()))
2 =create(TECHNICIANID,CUID,TURFS/TURF/0/AREANAME,TURFS/TURF/0/DEFAULT,
TURFS/TURF/0/ALTERNATE,TURFS/TURF/1/AREANAME,TURFS/TURF/1/DEFAULT
,TURFS/TURF/1/ALTERNATE).record(A1)
3 =file("validatedXmlToCSV.csv").export@ct(A2)

SPL 提供 JDBC 驱动程序供 Java 调用。只需将上面的 SPL 脚本存储为 xml2csv.splx 并在调用存储过程时在 Java 中调用它:

…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st=con.prepareCall("call xml2csv()");
st.execute();
…