2017-12-08 3 views
0

xslt 2 변형을 사용하여 텍스트 파일을 xml 파일로 변환하려고합니다.xslt2를 통해 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 

이 열이 "표"키 (탭)로 구분됩니다

텍스트 파일의 내용이다. 일부 열은 비어 있지만 탭 키는이 열을 다른 열과 구분하는 데 사용됩니다.

<?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> 

내가 XML을 생성 할 때 그래서 기초 : 그래서 (정규식은 단순화 된 형태가 아니라 그것을 최적화 할 수 있습니다 내 생각)

이 내 XSLT 파일입니다 이렇게 정규식을 사용했습니다 이 xslt 파일 (oxygen XML EDITOR에서 실행 됨)에서 열의 수가 < 일 때 1 초가 걸립니다. 열을 추가하면 대기 시간이 표시되고 XML 파일을 생성하는 데 15 초 이상 기다려야합니다 . XSLT 파일에서 99 개의 열을 처리해야하기 때문에 나에게 좋지 않습니다.

왜 성능에 문제가 있는지 말해 줄 수 있습니까? 어떻게해야합니까? 조언이 도움이 될 수 있습니다.

감사합니다.

+0

그래서 XSLT 프로세서를 oXygen과 함께 사용합니까? Saxon EE를 사용하여 성능이 향상되는지 여부를 시도해 보셨습니까? ''를 사용했는지 여부를 시도해 보셨습니까? ''regex-group (1)'대신 '이 더 잘 수행됩니까? –

+0

나는 Saxon-EE 9.3.0을 사용 중이며 같은 버전에서 PE & HE를 시도했다. 변경 사항 없음.tokenize 함수를 사용하지 않았습니다. 아마해야 해. 나는 그것이 작동하는지 알려줄 것입니다.) 감사합니다. – amin89

+0

@martin 내 코드를 토대로 토큰 화 기능을 가진 솔루션을 제공 할 수 있습니까? 내가 구현 한 것처럼 작동하지 않습니다. 미리 감사드립니다. – amin89

답변

1

우리의 의견 교환을 바탕으로 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')을 사용하십시오.

+0

많이 감사합니다;) – amin89

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이 제안한 것처럼 분리 기호로 탭에서 토큰 화하는 것이 훨씬 간단합니다.

관련 문제