我有一个使用xslt合并两个xml文件的代码,两个文件person1和person2的合并工作正常。我尝试了一个具有10 000条记录的示例,耗时17分钟,但是当记录数量为100 000时,大约需要6个小时才算是正常,或者我缺少某些东西。谢谢您的帮助。
第一档人员1:
<personnes>
<personne>
<name>aaa</name>
<age>10</age>
<adress>aaaaaa</adress>
</personne>
<personne>
<name>bbb</name>
<age>10</age>
<adress>aaaaaa</adress>
</personne>
<personne>
<name>ccc</name>
<age>20</age>
<adress>cccccc</adress>
</personne>
<personne>
<name>ddd</name>
<age>10</age>
<adress>cccccc</adress>
</personne>
</personnes>
第二个人2:
<personnes>
<personne>
<id>1111</id>
<quantity>1100</quantity>
</personne>
<personne>
<id>2222</id>
<quantity>2200</quantity>
</personne>
<personne>
<id>3333</id>
<quantity>3300</quantity>
</personne>
<personne>
<id>4444</id>
<quantity>4400</quantity>
</personne>
<personne>
<id>5555</id>
<quantity>5500</quantity>
</personne>
</personnes>
,我希望将结果保存在像下面这样的新xml文件中:
<personnes>
<personne>
<id>1111</id>
<name>aaa</name>
<quantity>1100</quantity>
<age>10</age>
<adress>aaaaaa</adress>
</personne>
<personne>
<id>2222</id>
<name>bbb</name>
<quantity>2200</quantity>
<age>10</age>
<adress>aaaaaa</adress>
</personne>
<personne>
<id>3333</id>
<name>ccc</name>
<quantity>3300</quantity>
<age>20</age>
<adress>cccccc</adress>
</personne>
<personne>
<id>4444</id>
<name>ddd</name>
<quantity>4400</quantity>
<age>10</age>
<adress>cccccc</adress>
</personne>
</personnes>
xslt文件:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<!-- load the merge file -->
<xsl:variable name="personne2"
select="document('file2.xml')"/>
<xsl:template match="/">
<personnes>
<xsl:for-each select="personnes/personne">
<xsl:variable name="elementposition" select="count(preceding-sibling::*)+1"/>
<!-- copy the child nodes -->
<personne>
<xsl:copy-of select="$personne2/personnes/personne[position() = $elementposition]/id"/>
<xsl:copy-of select="child::name"/>
<xsl:copy-of select="$personne2/personnes/personne[position() = $elementposition]/quantity"/>
<xsl:copy-of select="child::age"/>
<xsl:copy-of select="child::address"/>
</personne>
</xsl:for-each>
</personnes>
答案 0 :(得分:1)
似乎您可以简单地使用<xsl:variable name="elementposition" select="count(preceding-sibling::*)+1"/>
而不是<xsl:variable name="pos" select="position()"/>
,然后直接使用例如$personne2/personnes/personne[$pos]/id
,这可能会提高性能,因为无论如何有效地完成position()
功能的维护位置,而一次又一次地计数同级兄弟是昂贵的。
对于XSLT 2处理器,您还可以考虑将密钥与xsl:number
一起使用,例如
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="2.0">
<xsl:key name="pos" match="personne">
<xsl:variable name="pos" as="xs:integer">
<xsl:number/>
</xsl:variable>
<xsl:sequence select="$pos"/>
</xsl:key>
<xsl:output method="xml" indent="yes"/>
<!-- load the merge file
<xsl:variable name="personne2"
select="document('file2.xml')"/>-->
<!-- inlining here for the self-containedness of the example -->
<xsl:variable name="personne2">
<personnes>
<personne>
<id>1111</id>
<quantity>1100</quantity>
</personne>
<personne>
<id>2222</id>
<quantity>2200</quantity>
</personne>
<personne>
<id>3333</id>
<quantity>3300</quantity>
</personne>
<personne>
<id>4444</id>
<quantity>4400</quantity>
</personne>
<personne>
<id>5555</id>
<quantity>5500</quantity>
</personne>
</personnes>
</xsl:variable>
<xsl:template match="/">
<personnes>
<xsl:for-each select="personnes/personne">
<!-- copy the child nodes -->
<personne>
<xsl:copy-of select="key('pos', position(), $personne2)/id"/>
<xsl:copy-of select="child::name"/>
<xsl:copy-of select="key('pos', position(), $personne2)/quantity"/>
<xsl:copy-of select="child::age"/>
<xsl:copy-of select="child::address"/>
</personne>
</xsl:for-each>
</personnes>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bFN1y8Q
XSLT 3带有累加器和xsl:merge
的更多选项:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:accumulator name="pos" as="xs:integer" initial-value="0">
<xsl:accumulator-rule match="personnes" select="0"/>
<xsl:accumulator-rule match="personnes/personne" select="$value + 1"/>
</xsl:accumulator>
<xsl:mode use-accumulators="pos"/>
<xsl:output method="xml" indent="yes"/>
<!-- load the merge file
<xsl:variable name="personne2"
select="document('file2.xml')"/>-->
<!-- inlining here for the self-containedness of the example -->
<xsl:variable name="personne2">
<personnes>
<personne>
<id>1111</id>
<quantity>1100</quantity>
</personne>
<personne>
<id>2222</id>
<quantity>2200</quantity>
</personne>
<personne>
<id>3333</id>
<quantity>3300</quantity>
</personne>
<personne>
<id>4444</id>
<quantity>4400</quantity>
</personne>
<personne>
<id>5555</id>
<quantity>5500</quantity>
</personne>
</personnes>
</xsl:variable>
<xsl:template match="/*">
<xsl:copy>
<xsl:merge>
<xsl:merge-source select="personne">
<xsl:merge-key select="accumulator-before('pos')"/>
</xsl:merge-source>
<xsl:merge-source for-each-item="$personne2" select="personnes/personne">
<xsl:merge-key select="accumulator-before('pos')"/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:copy>
<xsl:copy-of
select="current-merge-group()[2]/id, name, current-merge-group()[2]/quantity, age, adress"/>
</xsl:copy>
</xsl:merge-action>
</xsl:merge>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>