我开发了通过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:stylesheet
或xsl:transform
根元素上的属性。
或者,如果您坚持使用XSLT 1,唯一的解决方法是在样式表中为该名称空间(例如pf1
)声明一个前缀(例如http://example.com/ns
)。 xmlns:pf1="http://example.com/ns"
,然后更改所有XPath表达式和匹配模式以使用前缀,以便root/rootnode/name
成为pf1:object/pf1:rootnode/pf1:name
。