2014-10-03 3 views
2

나는 더 나은 구조로 다른 파일로 변환하려는 약 100 개의 XML 파일을 가지고 있습니다. 이 예제에서는 이것을 CSV로 가져 오지만 더 나은 XML로 변환하는 변형도 있습니다. 형식이 저에게 의미가 없습니다. 이렇게 많은 질문이 있다는 것을 알았지 만 문제가 스타일 시트가 작동하지 않지만 너무 느리다는 것이 아니므로 예제를 적용하기가 어렵습니다.XSLT가 너무 느리게 작동합니다.

내 데이터 파일의 크기는 4-12MB입니다. 여기에 제공된 XSLT는 작은 파일에서도 잘 작동합니다. 예를 들어 250KB 조각으로 파일을 자르면 스타일 시트가 잘 처리됩니다 (약 30 초 정도 걸립니다). 실제로 더 큰 데이터 파일을 사용해 보았을 때 하나의 파일로도 작업을 완료하지 못하는 것 같습니다. 나는 Oxygen XML Editor를 가지고 있는데, 변형을 위해 Saxon-HE 9.5.1.2를 사용 해왔다.

한 발언 : 여전히 느려질 수 있습니다. 나는 밤새도록 또는 다른 것을 위해 컴퓨터를 떠날 수있다. 이것은 하나의 잘못된 데이터 세트에 관한 것이므로이 변환을 자주 반복 할 필요가 없습니다.

그래서 제 질문은 : 그것은 특히 느리게 작동하게이 XSLT에 뭔가

있습니까? 다른 승인이 더 잘 될까요?

다음은 간단한 작업 예제입니다. 실제 데이터 파일은 구조적으로 동일하지만이 예에서 "단어"라고 불리는 더 많은 노드가 있습니다. 유형은 내가 어떤 노드를 사용하는지 지정합니다. 방언 어와 정규화 된 버전을 가진 언어 방언 데이터입니다.

이것은 XML입니다.

<?xml version="1.0" encoding="UTF-8"?> 
<xml> 
<order> 
    <slot id="ts1" value="1957"/> 
    <slot id="ts2" value="1957"/> 
    <slot id="ts3" value="2389"/> 
    <slot id="ts4" value="2389"/> 
    <slot id="ts5" value="2389"/> 
    <slot id="ts6" value="2389"/> 
    <slot id="ts7" value="3252"/> 
    <slot id="ts8" value="3252"/> 
    <slot id="ts9" value="3252"/> 
    <slot id="ts10" value="3360"/> 
</order> 
<words type="original word"> 
    <annotation> 
     <data id_1="ts1" id_2="ts3"> 
      <text>dialectal_word_1</text> 
     </data> 
    </annotation> 
    <annotation> 
     <data id_1="ts4" id_2="ts7"> 
      <text>dialectal_word_2</text> 
     </data> 
    </annotation> 
    <annotation> 
     <data id_1="ts8" id_2="ts10"> 
      <text>,</text> 
     </data> 
    </annotation> 
</words> 
<words type="normalized word"> 
    <annotation> 
     <data id_1="ts2" id_2="ts5"> 
      <text>normalized_word_1</text> 
     </data> 
    </annotation> 
    <annotation> 
     <data id_1="ts6" id_2="ts9"> 
      <text>normalized_word_2</text> 
     </data> 
    </annotation> 
</words> 
</xml> 

이것은 XSLT입니다. XML 구조에서 일치하는 값을 가진 쌍을 선택하는 것입니다.

original normalized 
dialectal_word_1 normalized_word_1 
dialectal_word_2 normalized_word_2 
, 

그리고 나를 위해 잘 될 것입니다 : 출력을 무엇

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
<xsl:output method="text" encoding="UTF-8" indent="yes"/> 
<xsl:template match="/xml"> 
    <xsl:text>original&#x9;normalized 
</xsl:text> 
     <xsl:for-each select="words[@type='original word']/annotation/data"> 
      <xsl:sort select="substring-after(@id_1, 'ts')" data-type="number"/> 
      <xsl:variable name="origStartTimeId" select="@id_1"/> 
      <xsl:variable name="origEndTimeId" select="@id_2"/> 
      <xsl:variable name="origStartTime_VALUE" select="/xml/order/slot[@id=$origStartTimeId]/@value"/> 
      <xsl:variable name="origEndTime_VALUE" select="/xml/order/slot[@id=$origEndTimeId]/@value"/> 
        <xsl:value-of select="text"/> 
      <xsl:text>&#x9;</xsl:text>  
       <xsl:for-each select="/xml/words[@type='normalized word']/annotation/data"> 
        <xsl:variable name="normStartTime" select="@id_1"/> 
        <xsl:variable name="normEndTime" select="@id_2"/> 
        <xsl:variable name="normStartTime_VALUE" select="/xml/order/slot[@id=$normStartTime]/@value"/> 
        <xsl:variable name="normEndTime_VALUE" select="/xml/order/slot[@id=$normEndTime]/@value"/> 
        <xsl:if test="($normStartTime_VALUE = $origStartTime_VALUE) and ($normEndTime_VALUE = $origEndTime_VALUE)"> 
          <xsl:value-of select="text"/>  
        </xsl:if> 
       </xsl:for-each> 
      <xsl:text> 
</xsl:text> 
     </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

은 단순히 이것이다.

감사합니다.

답변

4

현재 스타일 시트의 중첩 된 for-each는 비효율적이며 파일 크기가 커짐에 따라 더 나 빠지게됩니다. (원래 단어의 수) * (정규화 된 단어의 수) 반복, 본질적으로 2 차 복잡성 (파일에 원본 단어와 정규화 된 단어의 수가 대략 같다고 가정). 을 사용하면 노드를 매우 빨리 찾을 수있는 조회 테이블을 구축 할 수 있습니다 (일반적으로 선형 시간이 아닌 일정 시간).

<!-- I've said version="2.0" to match your stylesheet in the question, but this 
    code is actually valid XSLT 1.0 as it doesn't use any 2.0-specific features 
    or functions --> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="text" encoding="UTF-8" indent="yes"/> 

    <!-- first key to look up slot elements by their id --> 
    <xsl:key name="slotById" match="slot" use="@id" /> 
    <!-- second key to look up normalized word annotations by the value of their slots --> 
    <xsl:key name="annotationBySlots" match="words[@type='normalized word']/annotation" 
      use="concat(key('slotById', data/@id_1)/@value, '|', 
         key('slotById', data/@id_2)/@value)" /> 

    <xsl:template match="/xml"> 
    <xsl:text>original&#x9;normalized&#xA;</xsl:text> 
    <xsl:apply-templates select="words[@type = 'original word']/annotation" /> 
    </xsl:template> 

    <xsl:template match="annotation"> 
    <xsl:value-of select="data/text" /> 
    <xsl:text>&#x9;</xsl:text> 
    <xsl:value-of select=" 
      key('annotationBySlots', 
       concat(key('slotById', data/@id_1)/@value, '|', 
         key('slotById', data/@id_2)/@value) 
      )/data/text" /> 
    <xsl:text>&#xA;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 

이 선형 시간에 (한 원래 워드 주석 당 "반복", 플러스 다시 슬롯의 수에 선형 플러스 정규화 수 있어야한다 룩업 테이블을 구축하는 데 걸리는 시간을 실행해야 단어 특수 효과).

+0

위의 설명에 감사드립니다. 그 결과를보고하기 위해서 : 처리 시간은 가장 큰 파일들과 1 초도되지 않고 2 초 정도 걸렸습니다. – nikopartanen

+3

일부 프로세서 (Saxon-EE는 예제 임)가이 최적화를 자동으로 수행 할 수 있음을 언급 할 가치가 있습니다. –

0

/xml/order/slot[@id=$origStartTimeId] 같은 구조는 <xsl:key name="slot-by-id" match="xml/order/slot" use="@id"/> 키를 정의한 다음 /xml/order/slot[@id=$origStartTimeId] 대신 을 사용합니다. 모든 장소에서 똑같은 변화를 가져라. 나는 확실히 공연이 증가한다.

관련 문제