如何优化XSLT以引用其他XML中的数据

时间:2013-08-08 08:19:00

标签: xslt

在输入XML文件中,与静态列一起,还可以使用期望来自其他文件(引用)的数据的列。 但是对于每个引用,输入xml具有相同ID或UID的单独行。

输出文件必须包含一行中的所有引用和关系(基于ID或UID)

我也为此转换编写了XSLT。当行计数较少(<100或<200)时,该XSLT更快。但是,随着计数的增长,输出xml生成需要很长时间(计数1000行,大约30分钟)。

我正在使用

<xsl:for-each select="z:row/@ID[generate-id() = generate-id(key('UniqueID',.))]">
XSLT中的

。因为对于输入xml的每一行中的相同ID,它必须检查多个引用(如section)和关系(如Child)并填充相同的列

输入原始XML文件。

<xml xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:z="#RowsetSchema">
<rs:data>
    <z:row UID="PARENT_001_1221AD_A878" GroupID="" GroupRel="" ID="37" Name="Outer Asset Details" RelProduct="Line1" RelUID="CHILD1_101_9899_9POOU99" RelName="CHILD1" RelType="Child" Size="22"/>
    <z:row UID="PARENT_001_1221AD_A878" GroupID="" GroupRel="" ID="37" Name="Outer Asset Details" RelProduct="Line1" RelUID="CHILD2_201_5646546_9890PBS" RelName="CHILD1" RelType="Child" Size="22"/>
    <z:row UID="PARENT_001_1221AD_A878" GroupID="" GroupRel="" ID="37" Name="Outer Asset Details" RelProduct="Line1" RelUID="SEC_999_99565_998AFSD" RelName="Hydraulic Section" RelType="Section" Size="22"/>
</rs:data>

Child.xml

<Child xsi:noNamespaceSchemaLocation="../XSD/Child.xsd" FILE="Child" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Row UID="CHILD1_101_9899_9POOU99">
    <Name>CHILD1</Name>
    <Description>This has details about the Hydraulic sections of the automobile</Description>
</Row>
<Row UID="CHILD2_201_5646546_9890PBS">
    <Name>CHILD2</Name>
    <Description>This has details about the manual sections of the automobile</Description>
</Row>

Section.xml

<Section xsi:noNamespaceSchemaLocation="../XSD/Section.xsd" FILE="Section" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Row UID="SEC_999_99565_998AFSD">
    <Name>Hydraulic Section</Name>
    <Description>This has details about the Sections in which the Hydraulic Systems are used.</Description>
</Row>

XSLT文件

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" exclude-result-prefixes="s dt z rs msxsl" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="UniqueID" match="z:row/@ID" use="."/>
<xsl:template match="/">
    <Parent xsi:noNamespaceSchemaLocation="../XSD/Parent.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" FILE="Parent">
        <xsl:for-each select="xml">
            <xsl:apply-templates select="rs:data"/>
        </xsl:for-each>
    </Parent>
</xsl:template>
<xsl:template match="rs:data">
    <xsl:for-each select="z:row/@ID[generate-id() = generate-id(key('UniqueID',.))]">
        <xsl:variable name="FRId">
            <xsl:value-of select="current()"/>
        </xsl:variable>
        <xsl:variable name="curNSet" select="//z:row[@ID=$FRId]"/>
        <xsl:copy-of select="current()"/>
        <Record>
            <xsl:attribute name="UID"><xsl:value-of select="$curNSet/@UID"/></xsl:attribute>
            <xsl:element name="Size">
                <xsl:value-of select="$curNSet/@Size"/>
            </xsl:element>
            <xsl:element name="Child">
                <xsl:apply-templates select="$curNSet[@RelType='Child']" mode="Relations">
                    <xsl:with-param name="RelType" select="'Child'"/>
                    <xsl:with-param name="DstFileName" select="'../Files/Child.xml'"/>
                </xsl:apply-templates>
            </xsl:element>
            <xsl:element name="Section">
                <xsl:apply-templates select="$curNSet[@RelType='Section']" mode="References">
                    <xsl:with-param name="RelType" select="'Section'"/>
                    <xsl:with-param name="DstFileName" select="'../Files/Section.xml'"/>
                </xsl:apply-templates>
            </xsl:element>
        </Record>
    </xsl:for-each>
</xsl:template>
<xsl:template match="z:row" mode="Relations">
    <xsl:param name="RelType"/>
    <xsl:param name="DstFileName"/>
    <xsl:element name="{$RelType}">
        <xsl:attribute name="DestinationKey"><xsl:value-of select="@RelUID"/></xsl:attribute>
        <xsl:attribute name="RelFilePath"><xsl:value-of select="$DstFileName"/></xsl:attribute>
        <xsl:attribute name="SequenceNumber"><xsl:value-of select="position()"/></xsl:attribute>
        <xsl:value-of select="@RelName"/>
    </xsl:element>
</xsl:template>
<xsl:template match="z:row" mode="References">
    <xsl:param name="DstFileName"/>
    <xsl:attribute name="DestinationKey"><xsl:value-of select="@RelUID"/></xsl:attribute>
    <xsl:attribute name="RelFilePath"><xsl:value-of select="$DstFileName"/></xsl:attribute>
    <xsl:attribute name="SequenceNumber"><xsl:value-of select="position()"/></xsl:attribute>
    <xsl:value-of select="@RelName"/>
</xsl:template>

的Output.xml

<Parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../XSD/Parent.xsd" FILE="Parent" ID="37">
<Record UID="PARENT_001_1221AD_A878">
    <Size>22</Size>
    <Child>
        <Child DestinationKey="CHILD1_101_9899_9POOU99" RelFilePath="../Files/Child.xml" SequenceNumber="1">CHILD1</Child>
        <Child DestinationKey="CHILD2_201_5646546_9890PBS" RelFilePath="../Files/Child.xml" SequenceNumber="2">CHILD1</Child>
    </Child>
    <Section DestinationKey="SEC_999_99565_998AFSD" RelFilePath="../Files/Section.xml" SequenceNumber="1">Hydraulic Section</Section>
</Record>

请帮我优化XSLT,以便更快地生成输出文件

1 个答案:

答案 0 :(得分:1)

考虑使用

<xsl:key name="UniqueID" match="z:row" use="@ID"/>

然后

<xsl:for-each select="z:row/@ID[generate-id() = generate-id(key('UniqueID',.))]">
        <xsl:variable name="FRId">
            <xsl:value-of select="current()"/>
        </xsl:variable>
        <xsl:variable name="curNSet" select="//z:row[@ID=$FRId]"/>

可以替换为

<xsl:for-each select="z:row[generate-id() = generate-id(key('UniqueID', @ID))]">
        <xsl:variable name="FRId" select="@ID"/>

        <xsl:variable name="curNSet" select="key('UniqueID', @ID"/>

我不确定您是否需要变量FRId,但使用select属性而不是嵌套value-of定义它肯定会消耗更少的资源。

制作

 <xsl:apply-templates select="$curNSet[@RelType='Child']" mode="Relations">

更有效地定义密钥

<xsl:key name="rel" match="z:row" use="concat(@ID, '|', @RelType)"/>

然后使用

 <xsl:apply-templates select="key('rel', concat(@ID, '|', 'Child')" mode="Relations">

然后对其他apply-templates使用相同的方法。

以上所有内容都是未经测试的,但应该给你一个想法。