Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无法使用xslt从xml到csv获取所需数据_Java_Xml_Csv_Xslt - Fatal编程技术网

Java 无法使用xslt从xml到csv获取所需数据

Java 无法使用xslt从xml到csv获取所需数据,java,xml,csv,xslt,Java,Xml,Csv,Xslt,我正在尝试将数据从XML加载到csv,但缺少一些节点数据。 下面是我的Java代码 import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.text.ParseException; import javax.xml.namespace.QNam

我正在尝试将数据从XML加载到csv,但缺少一些节点数据。 下面是我的Java代码

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;


public class XML2CSV {

public static int transform(InputStream is, OutputStream os, Transformer transformer, QName name) throws XMLStreamException, TransformerException {
    long time1 = System.nanoTime();
    // Open input & output files
    XMLInputFactory factory = XMLInputFactory.newInstance();
    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
    XMLStreamReader reader = factory.createXMLStreamReader(is);
    // In case you want to check which implementation is used.
    // Woodstox is a bit faster, but not worth adding extra dependency.
    Result result = new StreamResult(os);
    transformer.transform(new StAXSource(reader), result);

    int count = 0;
    while (reader.hasNext()) {
        if (reader.getEventType() == XMLStreamReader.START_ELEMENT && name.equals(reader.getName())) {
            // System.out.println("FOUND " + count);
            count++;

            if (count % 1000 == 0) {
                long time2 = System.nanoTime();
                double ms = (time2 - time1) / 1000000.0;
                System.out.format("Time=%.2fms Rows=%d%n", ms, count);
            }
        } else if (reader.getEventType() == XMLStreamReader.START_ELEMENT) {
//                    System.out.println("Start "+reader.getName()+" != "+name);
        }
        reader.next();
    }
    long time2 = System.nanoTime();
    double ms = (time2 - time1) / 1000000.0;
    System.out.format("Total Time=%.2fms Total rows=%d%n", ms, count);
    return count;
}

public static void main(String arg[]) throws Exception {
    // Parse command line options
    File xsltFile;
    File inputFile;
    File outputFile;
    String tagName;
    String namespace;
    try {
        String xsltFileName = parse("-x", arg, "XSLT sheet", true);
        String inputFileName = parse("-f", arg, "Input file", true);
        String outputFileName = parse("-o", arg, "Output file", true);
        tagName = parse("-t", arg, "Tag name", true);
        namespace = parse("-n", arg, "Tag Namespace URL", false);
        xsltFile = new File(xsltFileName);
        inputFile = new File(inputFileName);
        outputFile = new File(outputFileName);
    } catch (ParseException e) {
        System.err.println(e.getMessage());
        System.err.println("Syntax: XML2CSV -f <input file> -o <output file> -x <XSLT stylesheet> -t <Tag name> [-n <namespace URL>]");
        System.err.println("Will split given file on given tag with given namespace.");
        System.err.println("Will process contents of each tag using given XSLT.");
        System.exit(1);
        return;
    }
    if (!xsltFile.exists()) {
        System.err.println("File not found " + xsltFile.getAbsolutePath());
        System.exit(1);
    }
    if (!inputFile.exists()) {
        System.err.println("File not found " + inputFile.getAbsolutePath());
        System.exit(1);
    }

    // Open XSLT stylesheet
    StreamSource stylesource = new StreamSource(xsltFile);
    Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);

    // Create XML tag name which is used to break up XML into rows
    final QName name;
    if (namespace != null) {
        name = new QName(namespace, tagName);
    } else {
        name = new QName(tagName);
    }
    System.out.println("Will look for tag " + name + " in namespace " + namespace);

    FileOutputStream fos = null;
    FileInputStream fis = null;
    try {
        // Open input & output files
        fis = new FileInputStream(inputFile);
        fos = new FileOutputStream(outputFile);
        transform(fis, fos, transformer, name);
    } finally {
        if (fos != null) {
            fos.close();
        }
        if (fis != null) {
            fis.close();
        }
    }
}

// Teo - inefficient, but who cares
private static String parse(String option, String[] arg, String desc, boolean required) throws ParseException {
    for (int i = 0; i < arg.length; i++) {
        if (option.equals(arg[i])) {
            if (i + 1 < arg.length) {
                String value = arg[i + 1].trim();
                return value;
            } else {
                throw new ParseException(option + " must be followed by an argument", i);
            }
        }
    }
    if (required) {
        throw new ParseException(desc + " is required", 0);
    } else {
        return null;
    }
 }
}
请帮助我理解我在XSL代码中的错误所在,以及如何获取列数据


谢谢大家!

尝试使用设置蓄能器

<xsl:accumulator name="MktSegID" streamable="yes" as="xs:string?" initial-value="()">
  <xsl:accumulator-rule match="x:Batch/x:MktDef" select="string(@MktSegID)"/>
</xsl:accumulator>
使用



正如在一篇评论中所说的,它代替了
而出现了您想要的

好吧,在您的XML代码片段中,
Evnt
元素有一个属性为
Exch=“XLDX”
的父元素,因此它不是
。/../Exch
我想您想要
。/@Exch
。嗨,Martin,谢谢您的更新。那MktSegId呢?如何获取该属性?这是前面
MktDef
元素的
MktSegID
属性吗?好的,使用普通的XSLT/XPath,您可以导航到前面的sibling::MktDef[1]/@MktSegID元素,但我注意到您使用的是
和XSLT 3.0,因此可能无法导航。嗨,Martin,您能给我一些关于“前面的sibling::MktDef[1]/@MktSegID”的示例吗没有内存消耗,因为我有超过1 GB的xml文件数据要解析。您首先需要编辑您的问题以解释和显示输入xml的结构,目前尚不清楚xml的大小是由什么组成的,是否有一个
批处理
和一个
MktDef
以及数千个
SecDef
Evnt
子元素,或者是否有数千个
批处理
元素。因此,在不知道确切的重复结构的情况下,无法判断是否以及如何解决该任务。嗨,Martin,我已经更新了您上面提到的xsl s,但我遇到了以下错误,在google中尝试过,但无法了解错误是什么,致命错误:“错误检查表达式类型”funcall(之前的累加器,[literal expr(MktSegID)])'。:错误检查表达式“funcall(acculator before,[literal expr(MktSegID)])”的类型。线程“main”javax.xml.transform.TransformerConfigurationException中的异常:错误检查表达式“funcall”(acculator before,[literal expr(MktSegID)])的类型’。这是XSLT 3.0代码,使用流式处理,因此您需要使用Saxon 9.8 EE和
com.saxonica.config.StreamingTransformerFactory
Transformer Transformer=new com.saxonica.config.StreamingTransformerFactory().newTransformer(stylesource)
和提供SaxSource或StreamSource作为输入。否则,流式XSLT 3.0的全部使用是不可能的。嗨,马丁,谢谢你的快速响应。我试图将Saxon 9.8 EE添加到我的客户项目中,并了解到它不是一个自由软件,客户对此不满意,因为我们在这类项目上不会做太多工作XML文件。您能告诉我是否有免费软件可以获得此功能吗?提前谢谢!我不知道有任何开源XSLT 3.0实现支持流式传输。当然,SAX和XMLStreamReader是Java JRE的一部分,因此您需要使用这些API和使用它们编写的Java程序来创建CSV您好,Martin,非常感谢您的快速响应和宝贵的解决方案。
<?xml version="1.0" encoding="ISO-8859-1"?>
<FIXML xsi:schemaLocation="http://www.fixprotocol.org/FIXML-5-0-SP2 fixml-main-5-0-SP2_.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2" s="2012-04-23" v="FIX.5.0SP2">
<Batch ID="RPTTA111PUBLI20170509">
    ************ This is one set of loop************
           <MktDef MktID="XEUR" MktSegID="19699" EfctvBizDt="2017-05-11" NxtEfctvBizDt="2017-05-15" MktSeg="FCEA" MarketSegmentDesc="FUT ON EUR AUD" Sym="DE000A160WW0" ParentMktSegmID="FCUR" Ccy="AUD" MktSegStat="10" USFirmFlag="Y" PartID="1">
        <Undly Exch="XREU" Sym="CEA" ID="EU0009654748" Src="4" PrevClsPx="1.47"/>
    </MktDef>

    <SecDef PriSetPx="68708.52">
        <Instrmt ID="221096" Src="M" SecTyp="FUT" Status="1" Exch="XLDX" ProdCmplx="1" CFI="FFMCSX" MatDt="2024-12-17" MMY="202412" Mult="1" ValMeth="FUT" SettlMeth="C" PxPrcsn="2" MinPxIncr="0.01" MinPxIncrAmt="0.01">
            <Evnt EventTyp="7" Dt="2024-12-17"/>
        </Instrmt>
    </SecDef>
            <SecDef>
             .
             .
             .
            </SecDef>
            <SecDef>
             .
             .
             .
            </SecDef>
            <SecDef>
             .
             .
             .
            </SecDef>
   ************ This is one set of loop************
  ############ This will continue n number of times having millions of line###########        
</Batch>
</FIXML>
PriSetPx TxnTm ID Src EventTyp Dt Exch MktSegID 
<xsl:accumulator name="MktSegID" streamable="yes" as="xs:string?" initial-value="()">
  <xsl:accumulator-rule match="x:Batch/x:MktDef" select="string(@MktSegID)"/>
</xsl:accumulator>
<xsl:value-of select="concat($quote, normalize-space(../../../@MktSegID), $quote)" />
<xsl:value-of select="concat($quote, accumulator-before('MktSegID'), $quote)" />