将具有多个 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,'

')"/>
<xsl:for-each select="/TURFS/TURF">
<xsl:value-of select="concat(AREANAME,',',DEAFAULT,',',ALTERNATE,',

')"/>
</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 </xsl:text>
<!-- data -->
<xsl:for-each select="row">
<xsl:value-of select=".//*[not(*)]" separator=","/>
<xsl:text> </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();
…
我编写了一个 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,'

')"/>
<xsl:for-each select="/TURFS/TURF">
<xsl:value-of select="concat(AREANAME,',',DEAFAULT,',',ALTERNATE,',

')"/>
</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 </xsl:text>
<!-- data -->
<xsl:for-each select="row">
<xsl:value-of select=".//*[not(*)]" separator=","/>
<xsl:text> </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();
…