Python 使用函数时如何改善eXSLT性能问题 TL;博士:
似乎运行eXSLT要比XSLT2中的eXSLT慢得多。(7分钟对18小时) 下面我解释我的问题,用eXSLT和XSLT2写下相同转换的两个实现 当然,引擎是不同的,对于XSLT2我使用SaxonHE,对于eXSLT我使用python和lxml 最后,我请求帮助提高eXSLT部分的速度,因为我更喜欢使用python而不是JavaPython 使用函数时如何改善eXSLT性能问题 TL;博士:,python,xml,xslt,saxon,Python,Xml,Xslt,Saxon,似乎运行eXSLT要比XSLT2中的eXSLT慢得多。(7分钟对18小时) 下面我解释我的问题,用eXSLT和XSLT2写下相同转换的两个实现 当然,引擎是不同的,对于XSLT2我使用SaxonHE,对于eXSLT我使用python和lxml 最后,我请求帮助提高eXSLT部分的速度,因为我更喜欢使用python而不是Java 我必须将一个大的(~200k tier 1 elements)XML转换为csv 我有两个实现: 一个使用python,所以下面是libxml,我使用eXSL 另一个
我必须将一个大的(~200k tier 1 elements)XML转换为csv 我有两个实现:
- 一个使用python,所以下面是libxml,我使用eXSL李>
- 另一个使用SaxonHE,所以我使用XSL2转换
myf:printElement
,它接收一个元素和一个数字,该数字表示元素为空时必须写入的分隔符数
myf:printAttr
,它接收一个属性,并将其与分隔符一起打印
如果我还将分隔符定义为:
<xsl:param name="delim" select="','"/>
关于这一点,请注意:
- Child2可以在Tier1下重复,但只有一组给定的type值,不能重复
- 元素中也没有文本,这使得使用这两个函数的方法涵盖了我可能遇到的所有情况。尽管printAttr可能也适用于文本节点
- 我添加了列名以便于阅读。在代码中,我在开始时添加了它,一个包含eXSLT的内部节点集,一个包含XSLT2的简单字符串数组
- 撒克逊人需要7分钟
- 使用Python时,需要18小时
谢谢 在我看来,你似乎对这个问题的处理过度了 下面是简单的XSLT1.0转换
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" />
<xsl:template match="/root">
<xsl:text>T1_attr1,T1_attr2,C2_t1,C2_t2,C2_t3,C3_a,C4_Month,C4_Day,C4_Average</xsl:text>
<xsl:apply-templates select="Tier1" />
</xsl:template>
<xsl:template match="Tier1">
<xsl:text>
</xsl:text>
<xsl:value-of select="@attr1" /> <xsl:text>,</xsl:text>
<xsl:value-of select="@attr2" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child2[@type = '1']/@val" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child2[@type = '2']/@val" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child2[@type = '3']/@val" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/@a" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/Child4/@Month" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/Child4/@Day" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/Child4/@Average" />
</xsl:template>
</xsl:transform>
T1_属性1、T1_属性2、C2_T1、C2_t2、C2_t3、C3_a、C4_月、C4_日、C4_平均值
;
,
,
,
,
,
,
,
,
适用于
<root>
<Tier1 attr1="A" attr2="B">
</Tier1>
<Tier1 attr1="C" attr2="D">
<Child2 type="1" val="ABC" />
<Child2 type="3" val="123" />
</Tier1>
<Tier1 attr1="E" attr2="F">
<Child2 type="2" val="pancakes" />
<Child2 type="1" val="42" />
<Child3 a="H">
<Child4 Month="JUN" Day="3" Average="1200" />
</Child3>
</Tier1>
</root>
产生
T1_attr1,T1_attr2,C2_t1,C2_t2,C2_t3,C3_a,C4_Month,C4_Day,C4_Average
A,B,,,,,,,
C,D,ABC,,123,,,,
E,F,42,pancakes,,H,JUN,3,1200
T1_属性1、T1_属性2、C2_T1、C2_t2、C2_t3、C3_a、C4_月、C4_日、C4_平均值
A、 B,,,,,,,
C、 美国广播公司广播公司,,,,
E、 F,42,煎饼,H,6月,31200
真的是你的代码吗?规范未将任何显示为属性。当删除那些as
属性并在样式表中使用version=“1.0”
时,您是否获得了更好的性能(假设您当前有version=“2.0”
,否则我根本看不出您的代码片段为什么会工作)?是的,它可以工作,ofc version=“1.0”用于eXSLT,而“2.0”用于XSLT2。无论如何,我将尝试将作为删除,这可能是我从xslt2转换为eXSLT时留下的。奇怪的是,我没有得到任何错误。而且,在Pytom下运行XSLT2是不可行的……当出现version=“2.0”
样式表时,XSLT 1.0处理器应该尝试运行它。至于性能问题,如果在不使用Python的情况下(从命令行)使用xsltproc/libxslt,会发生什么情况?是否也需要那么长的时间?我还认为您可以简单地像
那样对模板
进行编码,并使用例如
而不是例如
。但显然,正确的方法是分析Python/libxslt代码,看看在哪里花时间来改进这些部分。否则很难说为什么要花这么长时间。是的,我可能对干燥原理有点偏见。我不喜欢有这么多重复的逗号,让元素在每一场比赛中分开对我来说似乎很好。但我不习惯于编写XSLT,也不习惯于应用在这个领域没有多大意义的标准。谢谢@Trompa此模板在几秒钟内就可以处理20MB的XML(~200k
元素,如图所示)。@Trompa DRY在XSLT中确实有意义,但有时使用内衬是最快的方式(我可能会补充说,也是最可读的方式)。它在您的环境中表现如何?(尝试Saxon和lxml)我正在做一个新的转换,以在原始文件中测试它。我会发布结果,但是Saxon和lxml之间的差异让人感觉很奇怪。好了,终于得到了结果。这是一个166M文件:PYT中的新XSLT:23.52s用户0.76s系统97%cpu 24.786总计
JVA中的新XSLT:78.86s用户0.96s系统407%cpu 19.606总计
JVA中的旧XSLT2:76.88s用户0.78s系统460%cpu 16.853总计
,因此,我猜函数的使用会增加很多开销。现在的差别是可以忽略的。谢谢!
<xsl:param name="break" select="'
'"/>
<xsl:template match="/">
<xsl:apply-templates select="root/Tier1"/>`
</xsl:template>
<xsl:template match="Tier1">
<xsl:value-of select="myf:printAttr(@attr1)"/>
<xsl:value-of select="myf:printAttr(@attr2)"/>
<xsl:value-of select="myf:printAttr(Child2[@type='1']/@val)"/>
<xsl:value-of select="myf:printAttr(Child2[@type='2']/@val)"/>
<xsl:value-of select="myf:printAttr(Child2[@type='3']/@val)"/>
<xsl:apply-templates/>
<!-- line break after each Tier1 -->
<xsl:if test="following-sibling::*">
<xsl:value-of select="$break"/>
</xsl:if>
</xsl:template>
<xsl:template match="Child3">
<xsl:value-of select="myf:printAttr(@a)"/>
<xsl:value-of select="ama:printElement(Child4,3)"/>
</xsl:template>
<xsl:template match="Child4">
<xsl:value-of select="myf:printAttr(@Day)"/>
<xsl:value-of select="myf:printAttr(@Month)"/>
<!-- We dont want comma after last element-->
<xsl:value-of select=@Average/>
</xsl:template>
T1_attr1, T1_attr2, C2_t1, C2_t2, C2_t3, C3_a, C4_Mont, C4_Day, C4_Average
A,B,,,,,,,
C,D,ABC,,123,,,,
E,F,42,pancakes,,H,JUN,3,1200
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" />
<xsl:template match="/root">
<xsl:text>T1_attr1,T1_attr2,C2_t1,C2_t2,C2_t3,C3_a,C4_Month,C4_Day,C4_Average</xsl:text>
<xsl:apply-templates select="Tier1" />
</xsl:template>
<xsl:template match="Tier1">
<xsl:text>
</xsl:text>
<xsl:value-of select="@attr1" /> <xsl:text>,</xsl:text>
<xsl:value-of select="@attr2" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child2[@type = '1']/@val" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child2[@type = '2']/@val" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child2[@type = '3']/@val" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/@a" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/Child4/@Month" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/Child4/@Day" /> <xsl:text>,</xsl:text>
<xsl:value-of select="Child3/Child4/@Average" />
</xsl:template>
</xsl:transform>
<root>
<Tier1 attr1="A" attr2="B">
</Tier1>
<Tier1 attr1="C" attr2="D">
<Child2 type="1" val="ABC" />
<Child2 type="3" val="123" />
</Tier1>
<Tier1 attr1="E" attr2="F">
<Child2 type="2" val="pancakes" />
<Child2 type="1" val="42" />
<Child3 a="H">
<Child4 Month="JUN" Day="3" Average="1200" />
</Child3>
</Tier1>
</root>
T1_attr1,T1_attr2,C2_t1,C2_t2,C2_t3,C3_a,C4_Month,C4_Day,C4_Average
A,B,,,,,,,
C,D,ABC,,123,,,,
E,F,42,pancakes,,H,JUN,3,1200