大文本文件通过xslt2转换为xml的性能问题

时间:2017-12-08 13:15:25

标签: xslt-2.0 oxygenxml

我尝试使用xslt 2转换将文本文件转换为xml文件。

这是文本文件的内容:

0000000001  0000000001  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford
0000000002  0000000002  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford
0000000003  0000000003  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford

这些列由" tabulation"分隔。键(标签)。某些列为空,但使用Tab键将此列与其他列分开。所以我使用正则表达式来做这个(正则表达式不是简化形式,但我认为它可以优化)

这是我的XSLT文件:

<?xml version="1.1" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    xmlns:xsi="setClients.xsd"
    exclude-result-prefixes="xs xd"
    version="2.0">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="txt-encoding" as="xs:string" select="'iso-8859-1'"/>
    <xsl:param name="txt-uri" as="xs:string" select="'file:///xxxxxxx.txt'"/>

    <xsl:variable name="txt" select="unparsed-text($txt-uri, $txt-encoding)"/>
    <xsl:variable name="entries" as="node()*">
        <xsl:analyze-string select="$txt" regex="\r\n?|\n">
            <xsl:non-matching-substring>
                <xsl:analyze-string select="." regex="(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)">
                    <xsl:matching-substring>
                        <entry>

                            <!-- * infos client -->
                            <c_id><xsl:value-of select="regex-group(1)"/></c_id>
                            <c_shipo_id><xsl:value-of select="normalize-space(regex-group(2))"/></c_shipo_id>
                            <c_company_id><xsl:value-of select="normalize-space(regex-group(3))"/></c_company_id>
                            <c_type_client><xsl:value-of select="normalize-space(regex-group(4))"/></c_type_client>
                            <c_classe><xsl:value-of select="normalize-space(regex-group(5))"/></c_classe>
                            <c_sous_type_client><xsl:value-of select="normalize-space(regex-group(6))"/></c_sous_type_client>
                            <c_start_date><xsl:value-of select="normalize-space(regex-group(7))"/></c_start_date>
                            <c_type_personne><xsl:value-of select="normalize-space(regex-group(8))"/></c_type_personne>
                            <c_type_personne><xsl:value-of select="normalize-space(regex-group(10))"/></c_type_personne>
                            <c_type_document><xsl:value-of select="normalize-space(regex-group(11))"/></c_type_document>
                            <c_num_tva><xsl:value-of select="normalize-space(regex-group(12))"/></c_num_tva>
                            <c_pays><xsl:value-of select="normalize-space(regex-group(13))"/></c_pays>
                            <c_pays_id><xsl:value-of select="normalize-space(regex-group(14))"/></c_pays_id>
                            <c_raison_sociale><xsl:value-of select="normalize-space(regex-group(15))"/></c_raison_sociale>
                            <c_civilité><xsl:value-of select="normalize-space(regex-group(16))"/></c_civilité>
                            <c_name><xsl:value-of select="normalize-space(regex-group(17))"/></c_name>
                            <c_prenom><xsl:value-of select="normalize-space(regex-group(18))"/></c_prenom>
                            <c_complement><xsl:value-of select="normalize-space(regex-group(19))"/></c_complement>
                            <c_adresse_forcee><xsl:value-of select="normalize-space(regex-group(20))"/></c_adresse_forcee>
                            <c_complement_adr><xsl:value-of select="normalize-space(regex-group(21))"/></c_complement_adr>
                            <c_numero><xsl:value-of select="normalize-space(regex-group(22))"/></c_numero>
                            <c_complement_numero><xsl:value-of select="normalize-space(regex-group(23))"/></c_complement_numero>
                            <c_adresse_rue><xsl:value-of select="normalize-space(regex-group(24))"/></c_adresse_rue>
                            <c_lieu_dit><xsl:value-of select="normalize-space(regex-group(25))"/></c_lieu_dit>
                            <c_code_postal><xsl:value-of select="normalize-space(regex-group(26))"/></c_code_postal>
                            <c_localite><xsl:value-of select="normalize-space(regex-group(27))"/></c_localite>
                            <c_telephone><xsl:value-of select="normalize-space(regex-group(28))"/></c_telephone>
                            <c_telephone_mobile><xsl:value-of select="normalize-space(regex-group(29))"/></c_telephone_mobile>
                            <c_email><xsl:value-of select="normalize-space(regex-group(30))"/></c_email>
                            <c_fax><xsl:value-of select="normalize-space(regex-group(31))"/></c_fax>
                            <c_actif><xsl:value-of select="normalize-space(regex-group(32))"/></c_actif>
                            <c_date_creation><xsl:value-of select="normalize-space(regex-group(33))"/></c_date_creation>
                            <c_langue><xsl:value-of select="normalize-space(regex-group(34))"/></c_langue>
                            <c_sapcode><xsl:value-of select="normalize-space(regex-group(35))"/></c_sapcode>
                            <c_invoicecopies><xsl:value-of select="normalize-space(regex-group(36))"/></c_invoicecopies>
                            <c_flttax><xsl:value-of select="normalize-space(regex-group(37))"/></c_flttax>
                            <c_flttax1><xsl:value-of select="normalize-space(regex-group(38))"/></c_flttax1>
                            <c_flttax2><xsl:value-of select="normalize-space(regex-group(39))"/></c_flttax2>
                            <c_flttax3><xsl:value-of select="normalize-space(regex-group(40))"/></c_flttax3>
                            <c_fldistax><xsl:value-of select="normalize-space(regex-group(41))"/></c_fldistax>
                            <c_equaladressbilling><xsl:value-of select="normalize-space(regex-group(42))"/></c_equaladressbilling>
                            <c_equaladressinvoice><xsl:value-of select="normalize-space(regex-group(43))"/></c_equaladressinvoice>
                            <c_equaladresspayment><xsl:value-of select="normalize-space(regex-group(44))"/></c_equaladresspayment>
                            <c_collectiontype><xsl:value-of select="normalize-space(regex-group(45))"/></c_collectiontype>
                            <c_companycode><xsl:value-of select="normalize-space(regex-group(46))"/></c_companycode>
                            <c_collectionid><xsl:value-of select="normalize-space(regex-group(47))"/></c_collectionid>
                            <c_duedatefree><xsl:value-of select="normalize-space(regex-group(48))"/></c_duedatefree>
                            <c_payements><xsl:value-of select="normalize-space(regex-group(49))"/></c_payements>
                            <c_paynum><xsl:value-of select="normalize-space(regex-group(50))"/></c_paynum>
                            <c_iban><xsl:value-of select="normalize-space(regex-group(51))"/></c_iban>
                            <c_mandate><xsl:value-of select="normalize-space(regex-group(52))"/></c_mandate>
                            <c_mandatedate><xsl:value-of select="normalize-space(regex-group(53))"/></c_mandatedate>
                            <c_expdate><xsl:value-of select="normalize-space(regex-group(54))"/></c_expdate>
                            <c_securitycode><xsl:value-of select="normalize-space(regex-group(55))"/></c_securitycode>
                            <c_authornum><xsl:value-of select="normalize-space(regex-group(56))"/></c_authornum>
                            <c_cardtype><xsl:value-of select="normalize-space(regex-group(57))"/></c_cardtype>
                            <c_bank><xsl:value-of select="normalize-space(regex-group(58))"/></c_bank>
                            <c_fixedue><xsl:value-of select="normalize-space(regex-group(59))"/></c_fixedue>
                            <c_duelastday><xsl:value-of select="normalize-space(regex-group(60))"/></c_duelastday>
                            <c_dateini><xsl:value-of select="normalize-space(regex-group(61))"/></c_dateini>
                            <c_datefin><xsl:value-of select="normalize-space(regex-group(62))"/></c_datefin>
                            <c_compfactid><xsl:value-of select="normalize-space(regex-group(63))"/></c_compfactid>
                            <c_persontype><xsl:value-of select="normalize-space(regex-group(64))"/></c_persontype>

                            <!-- * infos ptv -->

                            <p_id><xsl:value-of select="normalize-space(regex-group(65))"/></p_id>
                            <p_type><xsl:value-of select="normalize-space(regex-group(66))"/></p_type>
                            <p_useguide><xsl:value-of select="normalize-space(regex-group(67))"/></p_useguide>
                            <p_controldelivery><xsl:value-of select="normalize-space(regex-group(68))"/></p_controldelivery>
                            <p_copiesinitonclose><xsl:value-of select="normalize-space(regex-group(69))"/></p_copiesinitonclose>
                            <p_nominative><xsl:value-of select="normalize-space(regex-group(70))"/></p_nominative>
                            <p_sapcode><xsl:value-of select="normalize-space(regex-group(71))"/></p_sapcode>
                            <p_pays><xsl:value-of select="normalize-space(regex-group(72))"/></p_pays>
                            <p_raison_sociale><xsl:value-of select="normalize-space(regex-group(73))"/></p_raison_sociale>
                            <p_civilite><xsl:value-of select="normalize-space(regex-group(74))"/></p_civilite>
                            <p_nom><xsl:value-of select="normalize-space(regex-group(75))"/></p_nom>
                            <p_prenom><xsl:value-of select="normalize-space(regex-group(76))"/></p_prenom>
                            <p_complement><xsl:value-of select="normalize-space(regex-group(77))"/></p_complement>
                            <p_adresse_forcee><xsl:value-of select="normalize-space(regex-group(78))"/></p_adresse_forcee>
                            <p_complement_adr><xsl:value-of select="normalize-space(regex-group(79))"/></p_complement_adr>
                            <p_numero><xsl:value-of select="normalize-space(regex-group(80))"/></p_numero>
                            <p_complement_numero><xsl:value-of select="normalize-space(regex-group(81))"/></p_complement_numero>
                            <p_adresse_rue><xsl:value-of select="normalize-space(regex-group(82))"/></p_adresse_rue>
                            <p_lieu_dit><xsl:value-of select="normalize-space(regex-group(83))"/></p_lieu_dit>
                            <p_code_postal><xsl:value-of select="normalize-space(regex-group(84))"/></p_code_postal>
                            <p_localite><xsl:value-of select="normalize-space(regex-group(85))"/></p_localite>
                            <p_telephone><xsl:value-of select="normalize-space(regex-group(86))"/></p_telephone>
                            <p_telephone_mobile><xsl:value-of select="normalize-space(regex-group(87))"/></p_telephone_mobile>
                            <p_email><xsl:value-of select="normalize-space(regex-group(88))"/></p_email>
                            <p_fax><xsl:value-of select="normalize-space(regex-group(89))"/></p_fax>
                            <p_deliverydays><xsl:value-of select="normalize-space(regex-group(90))"/></p_deliverydays>
                            <p_active><xsl:value-of select="normalize-space(regex-group(91))"/></p_active>
                            <p_gestamp><xsl:value-of select="normalize-space(regex-group(92))"/></p_gestamp>
                            <p_numamp><xsl:value-of select="normalize-space(regex-group(93))"/></p_numamp>
                            <p_numcasieramp><xsl:value-of select="normalize-space(regex-group(94))"/></p_numcasieramp>
                            <p_numboxamp><xsl:value-of select="normalize-space(regex-group(95))"/></p_numboxamp>
                            <p_distributeur><xsl:value-of select="normalize-space(regex-group(96))"/></p_distributeur>
                            <p_enseigneamp><xsl:value-of select="normalize-space(regex-group(97))"/></p_enseigneamp>
                            <p_typeamp><xsl:value-of select="normalize-space(regex-group(98))"/></p_typeamp>
                            <zero><xsl:value-of select="normalize-space(regex-group(99))"/></zero>

                        </entry>

                    </xsl:matching-substring>
                </xsl:analyze-string>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:variable>

    <xsl:template match="/" name="text2xml">

        <clients>
            <xsl:for-each select="$entries">
                <client>
                    <xsl:attribute name="companyID">
                        <xsl:value-of select="c_company_id"/>
                    </xsl:attribute>
                    <xsl:attribute name="clientID" >
                        <xsl:value-of select="c_id"/>
                    </xsl:attribute>
                    <general>
                        <xsl:attribute name="startDate">
                            <xsl:value-of select="c_start_date"/>
                        </xsl:attribute>
                        <xsl:attribute name="country">
                            <xsl:value-of select="c_pays_id"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientType">
                            <xsl:value-of select="c_type_client"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientSubtype">
                            <xsl:value-of select="c_sous_type_client"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientClass">
                            <xsl:value-of select="c_classe"/>
                        </xsl:attribute>
                    </general>
                </client>


            </xsl:for-each>     
        </clients>
    </xsl:template>
</xsl:stylesheet>

因此,当我根据这个xslt文件(在氧气XML编辑器上执行)生成XML时,当列数<&lt;时,需要一秒钟来完成这些操作。 20.当我添加其他列时,会出现延迟,我应该等待超过15秒才能生成XML文件。这对我来说是件坏事,因为我需要在我的XSLT文件中处理99列。

你能告诉我为什么那里有性能问题吗? 我该怎么办? 任何建议都可以帮助我。

感谢。

2 个答案:

答案 0 :(得分:2)

我认为性能问题几乎肯定在正则表达式中

regex="(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)"

它表现不佳的原因是它具有高度模糊性,因此回溯。

请记住,.*会匹配尽可能多的字符 - 包括标签。所以它将从吞下整条线开始,然后意识到这不会导致匹配,然后回溯直到它找到一个制表符,然后意识到这再次失败,依此类推。最简单的解决方法是将每个(.*)替换为([^\t]*)(即除了制表符之外的任何字符序列)。但是,正如@MartinHonnen所建议的那样,将标签作为分隔符标记为更简单。

答案 1 :(得分:1)

根据我们在评论中的交流,我认为您可以尝试使用tokenize而不是xsl:analyze-string来替换方法,将输入解析为行,然后将行解析为列,看看是否表现更好。

使用tokenize的示例是

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">

   <xsl:variable name="tsv" as="xs:string">0000000001  0000000001  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford
0000000002  0000000002  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford
0000000003  0000000003  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford</xsl:variable>

   <xsl:output indent="yes"/>

   <xsl:variable name="lines" as="xs:string*" select="tokenize($tsv, '\r?\n')[normalize-space()]"/>
   <xsl:variable name="entries" as="node()*">

                    <xsl:for-each select="$lines">
                        <xsl:for-each select="tokenize(., '\s+')"><!-- if the input is really tab separated we need '\t' as the second argument for tokenize -->
                            <entry>
                                <col pos="{position()}">
                                    <xsl:value-of select="normalize-space()"/>
                                </col>
                            </entry>
                        </xsl:for-each>
                    </xsl:for-each>

    </xsl:variable>

    <xsl:template match="/" name="text2xml">

        <clients>
           <xsl:copy-of select="$entries"/>

            <xsl:for-each select="$entries">
                <client>
                    <xsl:attribute name="companyID">
                        <xsl:value-of select="c_company_id"/>
                    </xsl:attribute>
                    <xsl:attribute name="clientID" >
                        <xsl:value-of select="c_id"/>
                    </xsl:attribute>
                    <general>
                        <xsl:attribute name="startDate">
                            <xsl:value-of select="c_start_date"/>
                        </xsl:attribute>
                        <xsl:attribute name="country">
                            <xsl:value-of select="c_pays_id"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientType">
                            <xsl:value-of select="c_type_client"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientSubtype">
                            <xsl:value-of select="c_sous_type_client"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientClass">
                            <xsl:value-of select="c_classe"/>
                        </xsl:attribute>
                    </general>
                </client>


            </xsl:for-each>     
        </clients>
    </xsl:template>
</xsl:transform>

只需生成相同的列名称,即可根据自定义列名进行调整

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">

   <xsl:variable name="tsv" as="xs:string">0000000001  0000000001  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford
0000000002  0000000002  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford
0000000003  0000000003  ED  I   I       1900-01-01  I   VAT000000000000 BE  1   A       CO      S       451     LD      1010    Stanford</xsl:variable>

   <xsl:output indent="yes"/>

   <xsl:variable name="lines" as="xs:string*" select="tokenize($tsv, '\r?\n')[normalize-space()]"/>
   <xsl:variable name="entries" as="node()*">

                    <xsl:for-each select="$lines">

                            <entry>
                            <xsl:variable name="columns" select="tokenize(., '\s+')"/><!-- if the input is really tab separated we need '\t' as the second argument for tokenize -->
                          <c_id><xsl:value-of select="$columns[1]"/></c_id>
                            <c_shipo_id><xsl:value-of select="$columns[2]"/></c_shipo_id>
                            <c_company_id><xsl:value-of select="$columns[3]"/></c_company_id>
                            </entry>

                    </xsl:for-each>

    </xsl:variable>

    <xsl:template match="/" name="text2xml">

        <clients>

            <xsl:for-each select="$entries">
                <client>
                    <xsl:attribute name="companyID">
                        <xsl:value-of select="c_company_id"/>
                    </xsl:attribute>
                    <xsl:attribute name="clientID" >
                        <xsl:value-of select="c_id"/>
                    </xsl:attribute>
                    <general>
                        <xsl:attribute name="startDate">
                            <xsl:value-of select="c_start_date"/>
                        </xsl:attribute>
                        <xsl:attribute name="country">
                            <xsl:value-of select="c_pays_id"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientType">
                            <xsl:value-of select="c_type_client"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientSubtype">
                            <xsl:value-of select="c_sous_type_client"/>
                        </xsl:attribute>
                        <xsl:attribute name="clientClass">
                            <xsl:value-of select="c_classe"/>
                        </xsl:attribute>
                    </general>
                </client>


            </xsl:for-each>     
        </clients>
    </xsl:template>
</xsl:transform>

在线示例位于http://xsltransform.hikmatu.com/bFukv8fhttp://xsltransform.hikmatu.com/bFukv8f/1,用于标记相邻标签字符指示空列使用tokenize(., '\t')的列。