【问题标题】:can we use xslt transfrmation with SAX parser in Java?我们可以在 Java 中将 xslt 转换与 SAX 解析器一起使用吗?
【发布时间】:2017-06-30 07:56:14
【问题描述】:

我有一个 xm 文件,我已经使用 XSLT transformation 将其与 DOM 进行了解析,并将数据存储到 csv 中。

但现在我想在 SAX 中执行此操作,因为 xml 文件非常大。

现在我的问题是我们可以使用 xslt 转换和SAX parser 并将数据存储到 csv 中吗?

我到处搜索,但没有得到任何有用的信息。

这是我用 DOM 编写的 java 代码

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 {
    // Setting path for .xsl file
    File stylesheet = new File("style.xsl");

    // Setting path for Eurex xml feed file
    File xmlSource = new File("eurex_ref_data.xml");

    //Dom initialization and parse xml
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document document = builder.parse(xmlSource);

    // Transformation of parsed xml to csv
    StreamSource stylesource = new StreamSource(stylesheet);
    Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
    Source source = new DOMSource(document);
    //System.out.println(source.toString());
    System.out.println("Generating CSV File");
    Result outputTarget = new StreamResult(new File("AID.csv"));
    transformer.transform(source, outputTarget);
    System.out.println("File has been generated");
}
}

这是我的示例 XSLT 代码..

<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"/>

  <xsl:template match="/">
    <xsl:text>PriSetPx,TxnTm,ID,AltID,AltIDSrc</xsl:text>
    <xsl:text>&#xA;</xsl:text>
    <xsl:for-each select="FIXML/Batch/SecDef">
      <xsl:variable name="secDef" select="concat(@PriSetPx,',',@TxnTm)" />
      <xsl:for-each select="Instrmt/AID">
        <xsl:value-of select="concat($secDef, ',',../@ID,',',@AltID,',',@AltIDSrc,'&#xA;')"/>    
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

提前致谢!

【问题讨论】:

    标签: java xml csv xslt saxparser


    【解决方案1】:

    SAXSource https://docs.oracle.com/javase/8/docs/api/javax/xml/transform/sax/SAXSource.htmlStreamSource https://docs.oracle.com/javase/8/docs/api/javax/xml/transform/stream/StreamSource.html 所以你根本不需要使用 DOM 来使用 XSLT 和 Java。但是您必须了解 XSLT 1.0 和 2.0 在任何情况下都首先将完整的 XML 输入解析为对 XSLT/XPath 数据模型建模的树表示。因此,虽然 XSLT 1.0 或 2.0 处理器的本机树模型可能比 DOM 树消耗更少的内存,但它肯定会随着输入的大小而增长。

    至于您当前的代码,为避免显式使用 DOM,您可以简单地使用 StreamSource(或者如果您真的想要 SAXSource)而不是 transformer.transform(source, outputTarget); 中的 DOMSource

    所以使用例如

    File xmlSource = new File("eurex_ref_data.xml");
    Source source = new StreamSource(xmlSource);
    

    让 XSLT 处理器使用其本机树表示。

    如果您想处理非常大的 XML 文档并遇到内存问题,那么您可能需要研究 XSLT 3.0 和 streaming(目前由 Saxon 9 EE 支持,http://saxonica.com/html/documentation/using-xsl/embedding/jaxp-transformation.html),例如您添加到的样式表你的问题可以很容易地写成

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:math="http://www.w3.org/2005/xpath-functions/math"
        exclude-result-prefixes="xs math"
        version="3.0">
    
        <xsl:mode streamable="yes"/>
    
        <xsl:output method="text"/>
    
        <xsl:template match="/">
            <xsl:text>PriSetPx,TxnTm,ID,AltID,AltIDSrc</xsl:text>
            <xsl:text>&#xA;</xsl:text>
            <xsl:apply-templates select="FIXML/Batch/SecDef/Instrmt/AID"/>
        </xsl:template>
    
        <xsl:template match="AID">
            <xsl:value-of select="ancestor::SecDef/@PriSetPx, ancestor::SecDef/@TxnTm, ../@ID, @AltID, @AltIDSrc" separator=","/>
            <xsl:text>&#10;</xsl:text>
        </xsl:template>
    
    </xsl:stylesheet>
    

    然后很容易与 Saxon 9.7 或 9.8 EE (http://saxonica.com/download/download_page.xml) 和流式处理来创建 CSV,而无需消耗太多内存,因为 XSLT 和流式处理避免了首先构建完整输入的树,而是读取 XML只转发一次,逐个节点处理。

    如果您有非常大的输入文档(我不确定它们对 XSLT 的支持程度如何,它们专注于 XQuery),则可以考虑使用 BaseX 或 ExistDB 之类的 XML 数据库。

    【讨论】:

    • 嗨,马丁,感谢您的回复。我可以知道 SAXSource 和 SaxParser 是一样的吗?
    • 嗯,当然docs.oracle.com/javase/8/docs/api/javax/xml/parsers/…docs.oracle.com/javase/8/docs/api/javax/xml/transform/sax/… 不一样。如果您需要有关从 DOM 迁移到 SAX 的帮助,请开始阅读 API 或发布您当前使用 DOM 的代码。另一方面,我已经告诉过您,用于 XSLT 1.0 和 2.0 的 XSLT 处理器将首先处理完整的 XML 输入以构建树,因此您的内存问题可能会减少但不会消失。
    • 感谢 Martin,刚刚更新了我用 DOM 编写的代码以及 XSLT 代码。非常感谢!
    猜你喜欢
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 2012-04-25
    • 2022-01-04
    • 2012-07-13
    • 1970-01-01
    相关资源
    最近更新 更多