2013-11-21 2 views
2

I 다음 XSLT 스타일 시트가 간체 가지고노드 집합을 걷는 동안 소스 XML을 참조하는 방법은 무엇입니까?

이 (또한 단순화) 다음 원본 XML 문서를 말한다
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
exclude-result-prefixes="exsl"> 

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<xsl:variable name="categories"> 
    <category name="one"/> 
    <category name="two"/> 
    <category name="three"/> 
</xsl:variable> 

<xsl:template match="/"> 
<result> 

<xsl:for-each select="exsl:node-set($categories)/category"> 
<xsl:element name="{@name}"> 

<!-- THIS IS THE PROBLEMATIC PART --> 
    <xsl:for-each select="/input/object"> 
     <item> 
      <xsl:value-of select="."/> 
     </item> 
    </xsl:for-each> 

</xsl:element> 
</xsl:for-each> 
</result> 
</xsl:template> 
</xsl:stylesheet> 

:

<?xml version="1.0" encoding="utf-8"?> 
<input> 
    <object category="one">a</object> 
    <object category="one">b</object> 
    <object category="two">c</object> 
    <object category="one">d</object> 
    <object category="three">e</object> 
</input> 

소스 문서에 대한 참조가없는 결과를 생성하지; 출력은 각 카테고리에 하나씩 빈 요소입니다.

<?xml version="1.0" encoding="UTF-8"?> 
<result> 
    <one/> 
    <two/> 
    <three/> 
</result> 

원본 문서의 항목으로 요소를 어떻게 채울 수 있습니까?


분명히하기 위해이 문제는 다른 접근법을 사용하여 이미 해결되었습니다. 나는 단지 접근 방식이 작동하지 않는 이유를 이해하려고합니다.

답변

4

xsl:for-each에서 XPath는 선택한 "문서"의 컨텍스트로 해석됩니다. 즉, /node-set($categories)을 말합니다. 당신은 다음과 같은 코드를 시도하여 직접 볼 수 있습니다

<xsl:template match="/"> 
    <xsl:variable name="root" select="/"/> 
    <result> 

    <xsl:for-each select="exsl:node-set($categories)/category"> 
    <xsl:element name="{@name}"> 

    <xsl:for-each select="$root/input/object"> 
     <item> 
      <xsl:value-of select="."/> 
     </item> 
    </xsl:for-each> 

    </xsl:element> 
    </xsl:for-each> 
    </result> 
</xsl:template> 

은 내부 xsl:for-each 루프 템플릿에 의해 선택된 문서에 대한 액세스를 전달하는 변수 root을 사용합니다. (참고 :. 변수가 아니라 템플릿의 외부에 배치 된 수)

당신은 / 실제로 사용하는 한 번 확인 할 수있는 노드 집합 원래 코드에서 select="/category"에 의해 select="/input/object"를 대체하여. 요소에서 빈 항목 (범주 당 하나씩)을 가져옵니다.

+1

명확하고 잘 공식화 된 답변에 감사드립니다. 나는 node-set 함수가 자신의 루트를 가진 독립적 인 "document"를 생성한다는 것을 깨닫지 못했다. $ root 변수에 정확히 무엇이 저장되어 있는지 묻습니다. "호출하는"XML 문서의 루트에 대한 참조 일뿐입니까, 아니면 전체 트리를 저장합니까? 소스 XML이 상당히 커질 수 있으므로이 솔루션이 성능에 미칠 수있는 영향에 대해 우려하고 있습니다. –

+1

사실 나는 확실히 모른다. 그러나 불변 노드의 사본을 저장하는 것은 의미가 없으므로 노드 참조 여야합니다. 메모리는 아마 (노드 참조의) node-set에 의해서만 소비 될 것이고,'$ root'의 경우에는 작은 것 (하나의 요소) 일 것입니다. 'xsl : copy'와'xsl : copy-of'를 사용하여 노드 사본을 가진 변수를 가질 수 있습니다. http://www.biglist.com/lists/xsl-list/archives/200410/msg00710.html을보십시오. . – halfbit

+2

글쎄, 그럼. 나는 더 많은 검색을했는데 (여기서 _real_ 문제는 호출하는 문서로 되돌아 왔고, 필자는 내 검색에 초점을 맞출 수 있다고 지적했기 때문에) 변수에 루트를 저장하는 것이 일반적으로 주어진 조언이다. 나는 그것에 대해 걱정하지 않을 것입니다. 다시 한 번 감사드립니다. 즐거웠습니다. –

관련 문제