2011-01-29 2 views
2

<xsl:sort> 및 변수를 사용하여 XML 정렬에 관한 스레드를보고 있었지만 여전히 정렬 작업을 수행 할 수 없습니다. 여기에 상황에 대한 몇 가지 XML 구조입니다 :xsl : 변수별로 정렬

<records> 
    <record> 
    <contributors> 
     <authors> 
     <author>Author 1</author> 
     <author>Author 2</author> 
     </authors> 
    </contributors> 
    <titles> 
     <title>I'm a Title!</title> 
     <secondary-title></secondary-title> 
    </titles> 
    <dates> 
     <year>1901</year> 
    </dates> 
    </record> 
    <record>...</record> 
    <record>...</record> 
</records> 

는 그리고 여기에 관련 XSL입니다 : 나는에 문자열을 복사하는 경우

<xsl:variable name="sortby" 
       select="contributors/authors/author[1]" as="element()*"/> 
<xsl:for-each select="//record"> 
    <xsl:sort select="$sortby" order="ascending"/> 
    [a bunch of HTML to render the records as a bibliography] 
</xsl:for-each>   

변수의 속성 "선택"이 같은 종류에 붙여 넣습니다

<xsl:sort select="contributors/authors/author[1]" order="ascending"> 

그러면 작동합니다. 변수를 사용하면 그렇지 않습니다. 나는 그것을 사용하거나 사용하지 않고 시험해 보았다 as="element()*" - 도와 줘라?

+0

좋은 질문입니다. +1. 이 문제에 대한 일반적인 XSLT 솔루션이 없다는 대답에 대한 대답은 내 대답을 참조하십시오. 그러나 특정 문제와 유사한 문제의 큰 클래스를 해결하는 유연한 솔루션을 제공합니다. –

답변

0

xsl:sort 요소의 select= 부분에 변수를 사용할 수 없습니다. XSLT specification 상태 :

xsl:sort는 값이 표현되는 select 특성을 갖는다. 처리 할 각 노드에 대해 표현식은 해당 노드를 현재 노드로하고 정렬되지 않은 순서로 처리되는 노드의 전체 목록을 현재 노드 목록으로 평가합니다.

표현은하지 두 번 당신이 기대하는 것으로 만 을 평가한다. 표현식 $sortby은 한 번만 평가되어 매번 동일한 결과가 나타납니다 (실제 값은 xsl:variable 할당이 실행 된 시점의 현재 노드에 따라 다릅니다). 따라서 정렬은 선택한 요소의 순서를 변경하지 않습니다.

발견 한대로 특정 표현식을 정렬 기준으로 사용해야합니다.

+0

고마워, 그렉. 변수의 여는 태그와 닫는 태그 사이에 경로를 삽입하여 select 속성없이 변수를 사용하려고 시도했음을 언급 한 것을 잊어 버렸습니다. 그것도 작동하지 않았다. 내가 다음에 시도 할 수있는 것에 대한 제안이 있습니까? – Vika

+1

변수 표현식을 기준으로 정렬 할 수 없으며 필요한 이유를 설명하지 않았습니다. 특정 키 값을 기준으로 정렬하려면 질문 맨 아래에 설명 된대로'select' 속성에서 * actual * 표현식을 사용하십시오. –

+0

죄송합니다. 왜냐하면 결국 다양한 변수 (저자 이름, 연도, 게시자 별)를 기준으로 정렬하기 때문입니다. 최종 사용자에게 하이퍼 링크 또는 단추를 클릭하여 정렬 할 수있는 참고 문헌을 제시하고자합니다. 나는 JavaScript를 시도했지만 안정적으로 길을 잃었다. XSL 변수 또는 매개 변수를 사용하여이 작업을 수행하려고합니다. – Vika

1

일반적으로 XSLT/Xpath 1.0이나 XSLT/Xpath 2.0에서는 XPath 표현식의 동적 평가를 수행 할 수 없습니다.

내용에 제한이있는 경우 변수에 따라 정렬을 구현할 수 있습니다. 여기

은 특정 문제와 유사한 문제의 클래스를 해결 예입니다

<records> 
    <record> 
     <contributors> 
      <authors> 
       <author>X.Y.Z</author> 
       <author>A.B.C</author> 
      </authors> 
     </contributors> 
     <titles> 
      <title>Title B</title> 
      <secondary-title>Title AB</secondary-title> 
     </titles> 
     <dates> 
      <year>1901</year> 
     </dates> 
    </record> 
    <record> 
     <contributors> 
      <authors> 
       <author>T.U.V</author> 
       <author>D.E.F</author> 
      </authors> 
     </contributors> 
     <titles> 
      <title>Title A</title> 
      <secondary-title>Title BA</secondary-title> 
     </titles> 
     <dates> 
      <year>2001</year> 
     </dates> 
    </record> 
</records> 

을 :이 변환이 XML 문서에 적용

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:param name="pSortName" select="'authors'"/> 
<xsl:param name="pSortPosition" select="1"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="records"> 
    <records> 
    <xsl:apply-templates> 
    <xsl:sort select= 
    ".//*[name()=$pSortName]/* 
      [position()=$pSortPosition]"/> 
    </xsl:apply-templates> 
    </records> 
</xsl:template> 
</xsl:stylesheet> 

원하는 결과, 올바른 결과 (첫 번째 저자가 정렬 한 레코드)가 생성됩니다. :

<records> 
    <record> 
     <contributors> 
     <authors> 
      <author>T.U.V</author> 
      <author>D.E.F</author> 
     </authors> 
     </contributors> 
     <titles> 
     <title>Title A</title> 
     <secondary-title>Title BA</secondary-title> 
     </titles> 
     <dates> 
     <year>2001</year> 
     </dates> 
    </record> 
    <record> 
     <contributors> 
     <authors> 
      <author>X.Y.Z</author> 
      <author>A.B.C</author> 
     </authors> 
     </contributors> 
     <titles> 
     <title>Title B</title> 
     <secondary-title>Title AB</secondary-title> 
     </titles> 
     <dates> 
     <year>1901</year> 
     </dates> 
    </record> 
</records> 

우리에 매개 변수를 변경하는 경우 :

<xsl:param name="pSortName" select="'authors'"/> 
<xsl:param name="pSortPosition" select="2"/> 

다음 제 author 같은 정렬 키를 이용하여 변환 종류.

우리는에 매개 변수를 변경하는 경우 :

<xsl:param name="pSortName" select="'titles'"/> 
<xsl:param name="pSortPosition" select="1"/> 

다음과 같은 정렬 키 titles/title 요소를 사용하여 변환 정렬합니다.

우리는에 매개 변수를 변경하는 경우 :

<xsl:param name="pSortName" select="'titles'"/> 
<xsl:param name="pSortPosition" select="2"/> 

다음과 같은 정렬 키 titles/secondary-title 요소를 사용하여 변환 정렬합니다.

do note : 여기서 정렬 된 요소의 이름은 pSortName에 지정된 값과 동일하다고 가정합니다. 또한이 요소에는 자식 요소가 있고 pSortPosition은 정렬 키로 사용할 자식 위치를 지정한다고 가정합니다. 언급되지 않은

+0

+1. 재미있는 기술. – Flack

+0

+1 클래식 답변. –

1

다른 두 가지 솔루션 :

(A) 많은 프로세서 확장, DYN 같은라는 것이있다 : (평가) 문자열의 형태로 공급 XPath 식을 평가

(b) 일부 환경에서는 스타일 시트를 실행하기 전에 (물론 XSLT 변환을 사용하여) 스타일 시트를 수정하는 것이 가능합니다. 이렇게하면 필요한 XPath 표현식을 삽입 할 수 있습니다. XSLT 2.0에서는 정렬 키를 select="my:sort(.)"으로 작성한 다음 별도의 xsl : included 스타일 시트 모듈에 my : sort()를 정의 할 수 있습니다.

필자가 보았던 또 다른 관련 옵션은 외부 엔터티를 사용하는 것입니다 : select = "& sortkey;", 엔터티 참조는 프로그래밍 방식으로 XML 파서에 등록 된 EntityResolver를 사용하여 프로그래밍 방식으로 리디렉션 될 수 있습니다.

+0

+1. 좋은 메모. – Flack

+0

+1 그리고 이것들은 가능한 다른 대답들입니다. –