2016-07-08 2 views
2

나는이 같은 sophiscated 정렬이 있습니다어떻게 XSL 내부 변수를 선언하려면 다음을 수행-종류의

 <xsl:perform-sort select="$nodes"> 
     <xsl:sort select="if (p:isPreform(.) and not(p:getPreformPart(., $nodes))) then 1 else 0"/> 
     <xsl:sort select="p:getTargetPart(., $nodes)/../@pos"/> 
     <xsl:sort select="if (sort:isGroupElement(p:getTargetPart(., $nodes), $subsectionId)) then 
           sort:getGroupId(p:getTargetPart(., $nodes), $subsectionId) 
          else 
           p:getTargetPart(., $nodes)/@name"/> 
     <xsl:sort select="if (sort:isGroupElement(p:getTargetPart(., $nodes), $subsectionId)) then 0 else 1"/> 
     <xsl:sort select="replace(p:getTargetPart(., $nodes)/@number, '[А-Я]+$','')"/> 
     <xsl:sort select="if (p:isPreform(.)) then 1 else 0"/> 
     <xsl:sort select="@number"/> 
    </xsl:perform-sort> 

당신은 내부 구조를 반복 볼 수 있습니다. 어떻게 내가 이것을 리팩토링 할 수 있을까? 사양 그런 경우라면 내부 변수를 선언 할 수 없습니다 - 같은 조각처럼 보일 수 있습니다 :

 <xsl:perform-sort select="$nodes"> 
     <xsl:variable name="isPreform" select="p:isPreform(.)" as="xs:boolean"/> 
     <xsl:variable name="target" select="p:getTargetPart(., $nodes)" as="element()"/> 
     <xsl:variable name="isGrouped" select="sort:isGroupElement($target, $subsectionId)" as="xs:boolean"/> 

     <xsl:sort select="if ($isPreform and not(p:getPreformPart(., $nodes))) then 1 else 0"/> 
     <xsl:sort select="$target/../@pos"/> 
     <xsl:sort select="if ($isGrouped) then sort:getGroupId($target, $subsectionId) else $target/@name"/> 
     <xsl:sort select="if ($isGrouped) then 0 else 1"/> 
     <xsl:sort select="replace($target/@number, '[А-Я]+$','')"/> 
     <xsl:sort select="if ($isPreform) then 1 else 0"/> 
     <xsl:sort select="@number"/> 
    </xsl:perform-sort> 

어쩌면 내가 뭔가를 그리워? 그리고 저는 이것을 다른 방법으로 분류 할 수 있습니까?

미리 감사드립니다. 안드레이.

+0

변수 문제에 대한 해결책이 없지만 부울 조건에 따라 정렬하는 것처럼 보이는 '1' /'0'으로 계산 된 정렬 키가 있습니다. 부울은 완벽하게 정렬 할 수 있으므로이 표현식을 단축 할 수 있습니다. https://www.w3.org/TR/xquery-operators/#op.boolean이므로 'select = "if ($ isGrouped) then 0 else 1"'이 될 수 있습니다. 'select = "not ($ isGrouped))'''로 쓰여지고 다른 표현식에 대해서도 마찬가지입니다. –

+0

힌트를 보내 주셔서 감사합니다. 임시 구조를 생성하고 각 노드에 대해 계산 된 고유 ID와 for-each 내부의 특성을 저장 한 다음 perform-sort 내부에서이 특성을 가져 와서 정렬을 수행합니다. –

답변

1

아마 분명하지만, <xsl:perform-sort> 안에 변수를 추가하여 절충안을 찾는 대신 다음을 수행하는 것이 더 읽기 쉽습니다. 이것이 XSLT 2.0의 제작자가 허용하지 않은 한 가지 이유는 복잡성을 막는 것이 었습니다. 따라서 시퀀스 생성자가 <xsl:perform-sort>의 본문으로 허용되지 않았습니다. <xsl:apply-templates>의 본문 내에서 허용되지 않는 것과 같은 방식입니다.

내가 사용하는 (그리고 사용하는 모든 사람을 격려) 같은 것을 할이 :

여기
<xsl:perform-sort select="$nodes"> 
     <xsl:sort select="f:key1(., $nodes)"/> 
     <xsl:sort select="f:key2(., $nodes)"/> 
     <xsl:sort select="f:key3(., $nodes, $subsectionId)"/> 
     <xsl:sort select="f:key4(., $nodes, $subsectionId)""/> 
     <xsl:sort select="f:key5(., $nodes))"/> 
     <xsl:sort select="f:key6(.)"/> 
     <xsl:sort select="@number"/> 
    </xsl:perform-sort> 

나는 그것이 자연스럽게 이해 될 정도로 기능 f:keyN()에 대한 의미있는 이름을 가질 것입니다 무슨 정렬에 대한 규칙 아르.

반복되는 표현식은 별도의 함수로 구현할 후보이며 필요한 경우 다른 함수에서 호출합니다. 따라서 중복은 피할 수 있고 피할 수 있습니다. 이것은 추상화이라는 주요 프로그래밍 원리입니다.

+1

우리는 xsl : variable 앞에 XSLT 3.0에 대한 xsl : sort를 허용하라는 요청을 받았고 약간의 시간을 보냈지 만 놀랍도록 복잡해졌습니다 (변수는 입력 시퀀스의 각 항목에 대해 한 번 계산되어야합니다. 그렇다면 원래의 값을 유지해야 하는가?) 우리는 요구 사항이 메모 기능을 사용하여 더 잘 충족 될 수 있다고 결정했습니다. –

+0

@MichaelKay : 정확 하네! 구현 된 경우 이것은 XSLT에서 가장 추악한 기능이었을 것입니다. –