2010-05-13 6 views
3

아래의 XSL 2.0 코드를 사용하여 입력으로 제공 한 색인 목록이 들어있는 텍스트 노드의 ID를 찾습니다. 코드는 완벽하게 작동하지만 성능 측면에서 거대한 파일에 대해서는 오랜 시간이 걸립니다. 거대한 파일의 경우에도 인덱스 값이 작 으면 결과가 몇 밀리 초 만에 빠릅니다. 내가 XSL을 실행 saxon9he 자바 프로세서를 사용하고 있습니다. 상기 용액에 XSL 성능 향상

<xsl:variable name="insert-data" as="element(data)*"> 
    <xsl:for-each-group 
    select="doc($insert-file)/insert-data/data" 
    group-by="xsd:integer(@index)"> 
    <xsl:sort select="current-grouping-key()"/> 
    <data 
     index="{current-grouping-key()}" 
     text-id="{generate-id(
     $main-root/descendant::text()[ 
      sum((preceding::text(), .)/string-length(.)) ge current-grouping-key() 
     ][1] 
    )}"> 
     <xsl:copy-of select="current-group()/node()"/> 
    </data> 
    </xsl:for-each-group> 
</xsl:variable> 

인덱스 값이 너무 큰 경우는

실행할 XSL 걸리는 시간이다 83427ms 270,962 말한다. 거대한 파일에서 인덱스 값이 거대한 4605415, 4605431이라면 실행하는 데 몇 분이 걸립니다. 변수 "insert-data"의 계산이 전역 변수이지만 한 번만 계산되었지만 시간이 걸리는 것으로 보입니다. XSL을 추가하거나 프로세서를 추가해야합니까? 어떻게하면 XSL의 성능을 향상시킬 수 있습니까?

답변

2

나는이 문제를 추측에는 요는 text-id의 생성, 당신은 잠재적으로 여기 금액을 많이 다시 계산하는

 
generate-id(
    $main-root/descendant::text()[ 
     sum((preceding::text(), .)/string-length(.)) ge current-grouping-key() 
    ][1] 
) 

즉 표현이다. 여기서 가장 쉬운 방법은 문서에서 텍스트 노드를 반복하고, 지금까지 문자열 길이를 모으고, 요소를 새로 작성할 때마다 @index에 도달 할 때마다 접근 방식을 뒤집을 수있는 방법이라고 생각합니다. 다음 예는 접근 방식을 보여줍니다. 각각의 고유 한 @index 및 각 텍스트 노드는 한 번만 방문됩니다.

<xsl:variable name="insert-doc" select="doc($insert-file)"/> 

<xsl:variable name="insert-data" as="element(data)*"> 
    <xsl:call-template name="calculate-data"/> 
</xsl:variable> 

<xsl:key name="index" match="data" use="xsd:integer(@index)"/> 

<xsl:template name="calculate-data"> 
    <xsl:param name="text-nodes" select="$main-root//text()"/> 
    <xsl:param name="previous-lengths" select="0"/> 
    <xsl:param name="indexes" as="xsd:integer*"> 
     <xsl:perform-sort 
      select="distinct-values(
        $insert-doc/insert-data/data/@index/xsd:integer(.))"> 
      <xsl:sort/> 
     </xsl:perform-sort> 
    </xsl:param> 
    <xsl:if test="$text-nodes"> 
     <xsl:variable name="total-lengths" 
      select="$previous-lengths + string-length($text-nodes[1])"/> 
     <xsl:choose> 
      <xsl:when test="$total-lengths ge number($indexes[1])"> 
       <data 
        index="{$indexes[1]}" 
        text-id="{generate-id($text-nodes[1])}"> 
        <xsl:copy-of select="key('index', $indexes[1], 
              $insert-doc)"/> 
       </data> 
       <!-- Recursively move to the next index. --> 
       <xsl:call-template name="calculate-data"> 
        <xsl:with-param 
         name="text-nodes" 
         select="$text-nodes"/> 
        <xsl:with-param 
         name="previous-lengths" 
         select="$previous-lengths"/> 
        <xsl:with-param 
         name="indexes" 
         select="subsequence($indexes, 2)"/> 
       </xsl:call-template>      
      </xsl:when> 
      <xsl:otherwise> 
       <!-- Recursively move to the text node. --> 
       <xsl:call-template name="calculate-data"> 
        <xsl:with-param 
         name="text-nodes" 
         select="subsequence($text-nodes, 2)"/> 
        <xsl:with-param 
         name="previous-lengths" 
         select="$total-lengths"/> 
        <xsl:with-param 
         name="indexes" 
         select="$indexes"/> 
       </xsl:call-template>      
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
</xsl:template> 
+0

주셔서 감사합니다. 이것을 시도하고 곧 업데이트 할 것입니다. – Rachel

+1

위대한 답변은 몇 ms입니다. 그것은 82242에서 813으로 줄었습니다. 정말 고마워요 !! "데이터"노드의 값만 결과에 포함되지 않습니다. 줄 : . – Rachel

+1

@Rachel : 응답 시간이 향상되었다고 들었습니다. 원래의 키 정의에 버그가 있었지만 올바른 결과를 얻으려면''를 사용해야합니다. – markusk