我遇到XSLT问题转换大数据集(主机上为60 GB / 50000 Cylinder)。 该程序在Mainframe上运行,所以我没有得到他需要的2 GB Headsize。 但我并不知道为什么他需要这么多空间,也许有办法以更少的空间进行变换?我对XSLT一无所知,我需要一半的时间来做这件事^^
我的问题: 在XML中有许多我不需要的XML标签(在例如person_id,Iso_laender_code中),我想过滤所以我只得到那些我需要的人。
我的XML: 我有许多人物标签:
<ndm_message><message>
<Person>...</Person>
<Person>...</Person>
<Person>...</Person>...
每个人都有像姓名,地址等标签以及我不需要的许多标签
<Person>
<person_id>24</person_id>
<name>Person's Name</name>
</titel>
<Adresse>
<strasse>Irgendwo</strasse>
<iso_laender_code>004</iso_laender_code>
</Adresse>
</Person
我的XSLT: 我定义了一个白名单,并针对白名单检查每个人的任何节点:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsi:WhiteList>
<name>Person</name>
<name>name</name>
<name>Adresse</name>
<name>strasse</name>
</xsi:WhiteList>
<xsl:template match="/">
<ndm_message>
<xsl:for-each select="ndm_message/message/Person">
<xsl:call-template name="filter" >
<xsl:with-param name="Knoten" select="."/>
</xsl:call-template>
</xsl:for-each>
</ndm_message>
</xsl:template>
<xsl:template name="filter">
<xsl:param name="Knoten" />
<xsl:if test="$Knoten[name()=document('')/*/xsi:WhiteList/*]">
<xsl:copy>
<xsl:if test="not(child::*)">
<xsl:value-of select="$Knoten"/>
</xsl:if>
<xsl:for-each select="$Knoten/*">
<xsl:call-template name="filter" >
<xsl:with-param name="Knoten" select="."/>
</xsl:call-template>
</xsl:for-each>
<!-- -->
</xsl:copy>
</xsl:if>
</xsl:template>
我使用saxon9.jar在Java中运行XSLT。
public static void simpleTransform(String sourcePath, String xsltPath,
String resultDir) {
System.setProperty("javax.xml.transform.TransformerFactory",
"net.sf.saxon.TransformerFactoryImpl");
TransformerFactory tFactory = TransformerFactory.newInstance();
try {
Transformer transformer =
tFactory.newTransformer(new StreamSource(new File(xsltPath)));
transformer.transform(new StreamSource(new File(sourcePath)),
new StreamResult(new File(resultDir)));
} catch (Exception e) {
e.printStackTrace();
}
}
有人知道为什么他需要这么多空间吗?我认为XSLT仅引用一个Person并且标签是递归的,一个/ Person大约是32 KB。 也许问题是StreamSource和Result? 还有其他方法可以使用XSLT和更少的空间吗?
非常感谢 弗洛里安
答案 0 :(得分:2)
这是一个XSLT 3.0样式表,您可以使用Saxon 9 EE来输入streaming processing:
<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:param name="STREAMABLE" static="yes" as="xs:boolean" select="true()"/>
<xsl:mode _streamable="{$STREAMABLE}" on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="white-list">
<name>Person</name>
<name>name</name>
<name>Adresse</name>
<name>strasse</name>
</xsl:param>
<xsl:template match="ndm_message">
<xsl:copy>
<xsl:apply-templates select="message/Person"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Person//*[not(local-name() = $white-list/name)]"/>
</xsl:stylesheet>
它转换输入样本
<ndm_message>
<message>
<Person>
<person_id>24</person_id>
<name>Person 24</name>
<titel>Ein Titel</titel>
<Adresse>
<strasse>Strasse 24</strasse>
<iso_laender_code>004</iso_laender_code>
</Adresse>
</Person>
<Person>
<person_id>25</person_id>
<name>Person 25</name>
<titel>Ein Titel</titel>
<Adresse>
<strasse>Strasse 25</strasse>
<iso_laender_code>004</iso_laender_code>
</Adresse>
</Person>
</message>
</ndm_message>
进入输出样本
<ndm_message>
<Person>
<name>Person 24</name>
<Adresse>
<strasse>Strasse 24</strasse>
</Adresse>
</Person>
<Person>
<name>Person 25</name>
<Adresse>
<strasse>Strasse 25</strasse>
</Adresse>
</Person>
</ndm_message>
至于使用Java运行它,我认为使用XSLT 3.0和流式传输它更好(甚至是必要的,请参阅https://saxonica.plan.io/issues/3120)来使用Saxon特定的API http://saxonica.com/html/documentation/using-xsl/embedding/s9api-transformation.html而不是JAXP。
答案 1 :(得分:0)
感谢您的解决方案,但XSLT Streaming声音很难,我通常编程COBOL ^^ 我决定使用Stax-parser编写Java Programm,并根据文件中的“白名单”检查XML-Tag。这对我来说比较简单,我可以用UTF-8读取并写入EBCDIC,所以我在我的JCL中保存了一个编码转换步骤:-) 但非常感谢你的帮助。