大数据的XSLT性能问题

时间:2015-02-19 06:24:51

标签: xslt

我的xslt代码存在性能问题:  这是我的输入文件:

<?xml version="1.0" encoding="UTF-8"?>
<Products>
    <Product ID="111111" Type="Item" ParentID="7402">
        <Name>ABC</Name>
        <Values>
            <Value AttributeID="11">8.00</Value>
            <Value AttributeID="12">8.00</Value>
            <Value AttributeID="13">0.18</Value>
        </Values>
        <Product ID="B582B65D" Type="UID" ParentID="111111">
            <Values>
                <Value AttributeID="11">8.00</Value>
                <Value AttributeID="12">8.00</Value>
                <Value AttributeID="13">0.18</Value>
                <Value AttributeID="14">0.18</Value>
            </Values>
        </Product>
    </Product>
    <Product ID="222222" Type="Item" ParentID="7402">
        <Name>XYZ</Name>
        <Values>
            <Value AttributeID="12">8.00</Value>
            <Value AttributeID="13">8.00</Value>
            <Value AttributeID="15">0.18</Value>
        </Values>
        <Product ID="B582B65D" Type="UID" ParentID="111111">
            <Values>
                <Value AttributeID="11">8.00</Value>
                <Value AttributeID="12">8.00</Value>
                <Value AttributeID="16">0.18</Value>
                <Value AttributeID="18">0.18</Value>
            </Values>
        </Product>
    </Product>
</Products>

这是我的转换代码:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math"
    extension-element-prefixes="math">
    <xsl:output method="xml" indent="yes" />
    <xsl:param name="file2" select="document('Mapping.xml')" /> 
    <xsl:template match="/Products">
        <Products>
         <xsl:for-each select="Product">
            <xsl:call-template name="item" />
         </xsl:for-each>        
        </Products>
    </xsl:template>
    <xsl:template name="item">
        <Product type="{./@Type}" ID="{./@ID}">
        <xsl:for-each select="./Values/Value">
                <xsl:variable name="Idval" select="@AttributeID" />
                <xsl:element name="{$file2//Groups/AttributeID[@ID=$Idval]/@group}">
                <xsl:element name="{$file2//Groups/AttributeID[@ID=$Idval]}">
                     <xsl:attribute name="ID"><xsl:value-of select="$Idval"/></xsl:attribute>
                    <xsl:value-of select="." />
                </xsl:element>
                </xsl:element>
            </xsl:for-each>         
            <xsl:call-template name="uid" />
        </Product>
    </xsl:template>
    <xsl:template name="uid">
        <Product type="{./Product/@Type}" ParentId="{./Product/@ParentID}">
            <xsl:for-each select="./Product/Values/Value">
                <xsl:variable name="Idval" select="@AttributeID" />
                <xsl:element name="{$file2//Groups/AttributeID[@ID=$Idval]/@group}">
                <xsl:element name="{$file2//Groups/AttributeID[@ID=$Idval]}">
                     <xsl:attribute name="ID"><xsl:value-of select="$Idval"/></xsl:attribute>
                    <xsl:value-of select="." />
                </xsl:element>
                </xsl:element>
            </xsl:for-each>
        </Product>
    </xsl:template>
</xsl:stylesheet>

以上xslt使用下面的xml文件将属性id映射到相应的名称和组 Mapping.xml

<?xml version="1.0" encoding="UTF-8"?>
<Groups>
    <AttributeID ID="11" group="Pack1">Height</AttributeID>
    <AttributeID ID="12" group="Pack2">Width</AttributeID>
    <AttributeID ID="13" group="Pack1">Depth</AttributeID>
    <AttributeID ID="14" group="Pack3">Length</AttributeID>
    <AttributeID ID="15" group="Pack3">Lbs</AttributeID>
    <AttributeID ID="16" group="Pack4">Litre</AttributeID>
</Groups>

3 个答案:

答案 0 :(得分:4)

替换

等表达式的使用
select="$file2//Groups/AttributeID[@ID=$Idval]"

带钥匙:

<xsl:key name="ID" match="Groups/AttributeID" use="@ID"/>

然后

select="key('ID', $IDval, $file)"/>

另外,Saxon-EE会自动为您进行优化。

带有3个参数的key()函数是XSLT 2.0语法。如果您不幸使用XSLT 1.0,则必须编写一个虚拟xsl:for-each,使$ file成为上下文项,因为key()只会在包含上下文项的文档中进行选择。

答案 1 :(得分:1)

为交叉文档查找定义一个键:<xsl:key name="by-id" match="Groups/AttributeID" use="@ID"/>,然后(假设一个XSLT 2.0处理器),您可以简化<xsl:element name="{$file2//Groups/AttributeID[@ID=$Idval]/@group}"><xsl:element name="{key('by-id', @AttributeID, $file2)/@group">之类的表达式。对您拥有的其他交叉引用进行相同的更改,即所有$file2//Groups/AttributeID[@ID=$Idval]表达式都应使用键查找。

答案 2 :(得分:0)

简化假设您的第二个文件不是太大,您希望将值折叠到模板中。它也适用于XSLT 1.0。像这样:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math"
extension-element-prefixes="math">
<xsl:output method="xml" indent="yes" />

<xsl:template match="/">
    <Products>
        <xsl:apply-templates select="/Products/Product" />
    </Products>
</xsl:template>

<xsl:template match="Product">
    <xsl:element name="Product">
        <xsl:apply-templates select="@*" />
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="Name">
    <Name>
        <xsl:value-of select="." />
    </Name>
</xsl:template>

<xsl:template match="@*">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="." />
    </xsl:attribute>    
</xsl:template>

<xsl:template match="Values">
    <Values>
        <xsl:apply-templates />
    </Values>
</xsl:template>

<!-- Templates for individual AttributeIDs, only when there are few -->

<xsl:template match="Value[@AttributeID='11']">
    <Pack1>
        <xsl:element name="Height">
            <xsl:attribute name="ID">
                <xsl:value-of select="@AttributeID" />
            </xsl:attribute>
            <xsl:value-of select="." />
        </xsl:element>
    </Pack1>
</xsl:template>

<!-- Repeat for the other AttributeID values -->

</xsl:stylesheet>

(键入我的头,将包含拼写错误)

当然,如果它很大,迈克尔的建议是最好的行动方案。