我开发了通过xsl将xml转换为cvs的应用程序。我使用DOM API,但性能不佳(在输入中,我有100000 xml大小为200kb-20mb),我尝试使用SAX API,但在转换后收到错误的结果输出。
Dom API:

@PostConstruct
public void init() throws ParserConfigurationException, TransformerConfigurationException {
    styleSheet = new File("1.xsl");
    builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    stylesource = new StreamSource(styleSheet);
    transformer = TransformerFactory.newInstance().newTransformer(stylesource);
}

public String transformXmlToCsv(String inputXml) {
    String csv = null;

    try {
        InputSource is = new InputSource(new StringReader(inputXml));

        Document document = builder.parse(is);

        StringWriter writer = new StringWriter();

        transformer.transform(new DOMSource(document), new StreamResult(writer));
        csv = writer.toString();
        writer.close();
    } catch (Exception e) {
        LOGGER.error("Exception during transorming", e);
    }
    return csv;
}


}

SAX API:

 public static void main(String[] args) throws Exception {
    TransformerFactory transFact = TransformerFactory.newInstance( );
    File xml = new File("019dc124-5057-43f3-aa5d-1d840536b1b5-1558467374000.xml");
    File styleSheet = new File("1.xsl");
    Result outputTarget = new StreamResult(new File("C:\\proj\\xmlparser\\result.csv"));
    Source stylesource = new StreamSource(styleSheet);
    Transformer trans = transFact.newTransformer(stylesource);
    InputSource is = new InputSource(new FileReader(xml));
    Source xmlSource = new SAXSource(is);
    trans.transform(xmlSource, outputTarget);
}

最佳答案

我认为您可能只是遇到了有关正确使用XSLT在名称空间中选择元素的最常见问题的变体,我认为默认的Java DocumentBuilder不支持名称空间,因此您的XSLT代码可能会将默认名称空间中的元素视为在没有命名空间的情况下,以便您使用root/rootnode/name之类的路径。另一方面,使用Sax我认为XSLT处理器将在您说的默认名称空间中看到元素,然后您的路径不再起作用,因为它们在无名称空间中选择了元素。

要解决此问题,有两种方法:将Saxon 9 HE(最新版本为9.9)放在类路径上以切换到XSLT 2/3,然后使用例如xpath-default-namespace="http://example.com/ns"作为xsl:stylesheetxsl:transform根元素上的属性。

或者,如果您坚持使用XSLT 1,唯一的解决方法是在样式表中为该名称空间(例如pf1)声明一个前缀(例如http://example.com/ns)。 xmlns:pf1="http://example.com/ns",然后更改所有XPath表达式和匹配模式以使用前缀,以便root/rootnode/name成为pf1:object/pf1:rootnode/pf1:name

07-27 13:59