2012-01-25 4 views
2

xml에는 사람 목록, 데이터베이스 ID 및 이들 간의 관계 목록이 있습니다. 나는 자바에서 XSLT 1.0을 사용하여 생성하고 싶습니다 xsl 상관 관계를 색인하기위한 식별자

<root> 
    <person> 
    <id>1000</id> 
    <name>p1</name> 
    </person> 
    <person> 
    <id>1001</id> 
    <name>p2</name> 
    </person> 
    <rel> 
    <personid>1001</personid> 
    <personid>1000</personid> 
    </rel> 
</root> 

다음 :

person 2 relates to person 1. 

논리가 나타나는 순서에 따라 사람의 인덱스를 보여주는 것입니다 그것은 다음과 같습니다 XML로.

나의 현재 아이디어 :

  • 자바에서 XML을 전처리와 함께 XSL에 PARAM으로지도를 보내 [person_id로, person_index] 다음 각 관계에 대한 XPath를 만드는 person_id로
  • 에서 person_index를 얻을 수 xsl에서 주어진 id로 사람의 인덱스를 찾는다. (xpath를 만들지는 모르겠지만)
  • java에서 전처리하고 맵을 구성하여이를 ThreadLocal 변수에 넣은 다음 xsl에서 다른 것을 호출한다. 이 ThreadLocal을 사용하여 사람 ID에서 사람 색인을 얻는 방법

다른 모든 아이디어는 잘하면 매우 간단합니다.

감사합니다.

+0

이 질문에 대한 대답은 아니지만 단일 데이터 필드에 특성을 사용하는 것이 좋습니다. 예를 들어, 대신 을 사용할 수 있습니다. 읽기 쉽고 SAX로 더 쉽게 파싱 할 수 있습니다. –

+0

고마워, 실제로 XML 구조체를 제어하지 못한다. 다른 응용 프로그램에서 온 것이다. –

답변

1

Java 사전 처리 또는 매핑이 필요하지 않습니다.

<xsl:key name="kPersonById" match="person" use="id" /> 

<xsl:template match="rel"> 
    <xsl:text>Person </xsl:text> 
    <xsl:value-of select="key('kPersonById', personid[1])/name" /> 
    <xsl:text> relates to </xsl:text> 
    <xsl:value-of select="key('kPersonById', personid[2])/name" /> 
    <xsl:text>.&#10;</xsl:text> 
</xsl:template> 

이렇게하면 <rel>마다 한 줄의 텍스트가 생성됩니다. 그것은 완전한 스타일 시트가 아니며, 나머지를 알아낼 것입니다.

+0

혼란스럽게 생각합니다.하지만 사람 1은 xml 순서가있는 사람을 의미합니다. 1. 이름 태그 값 (p1)을 사용하고 싶지 않습니다. 가능한가? –

+0

@dan : 물론 가능합니다.''key (...)/count (preceding-sibling :: person) + 1 ''을 사용하십시오. – Tomalak

+0

이렇게하는 것이 좋은 방법입니다. 신속한 답변에 감사드립니다. 감사합니다! –

1

내가 더 나은 방법이있을 확신하지만,이 작품 :

을 Dimitre에서 좋은 조언에 응답 -이 솔루션은 XLST 2.0을 사용 할 수있는에 의존하고 있습니다. XLST 1.0에서 변수는 "결과 트리 단편"이므로 saxon : parse와 같은 확장자를 사용하지 않고 xpath를 추가하여 사용할 수 없습니다.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
version="2.0"> 

<xsl:variable name="indexed"> 
    <xsl:apply-templates select="root/person"/> 
</xsl:variable> 

<xsl:template match="/"> 
    <xsl:apply-templates select="root/rel"/>   
</xsl:template> 

<xsl:template match="root/person"> 
    <xsl:copy> 
     <index> 
      <!-- concern - will this make the approach take O(n^2) and 
       therefore get very slow for large input docs --> 
      <xsl:number/> 
     </index> 
     <xsl:copy-of select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="root/rel"> 
    <xsl:variable name="p1" select="personid[1]/text()"/> 
    <xsl:variable name="p2" select="personid[2]/text()"/> 
    <xsl:text>Person </xsl:text> 
    <xsl:value-of select="$indexed/person[id = $p1]/index"/> 
    <xsl:text> relates to person </xsl:text> 
    <xsl:value-of select="$indexed/person[id = $p2]/index"/> 
</xsl:template> 
</xsl:stylesheet> 
+0

이 대답은 XSLT 2.0 솔루션이라는 것을 언급하십시오. 그렇지 않으면 사람이이 중요한 사실에 주목할 것입니다. XSLT 2.0에서 거의 아무 것도 사용하지 않으므로 XSLT 1.0 솔루션 (또는 진정한 XSLT 2.0 솔루션)을 만들지 않으시겠습니까? 마지막으로,이 해결책은 많은'person'과'rel' 요소에 대해 느릴 수 있습니다. –

1

가 (2 인 이상과의 관계와 함께 작동)이 변환 :

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kPersonById" match="person" use="id"/> 

<xsl:template match="rel/personid"> 
    <xsl:variable name="vPersInd" select= 
    "count(key('kPersonById', .) 
      /preceding-sibling::person 
     ) 
      +1 "/> 
    <xsl:text> is related to person </xsl:text> 

    <xsl:value-of select="$vPersInd"/> 
</xsl:template> 

<xsl:template match="rel/personid[1]"> 
    <xsl:variable name="vPersInd" select= 
    "count(key('kPersonById', .) 
      /preceding-sibling::person 
     ) 
      +1 "/> 
    person <xsl:value-of select="$vPersInd"/><xsl:text/> 
</xsl:template> 

<xsl:template match="text()"/> 
</xsl:stylesheet> 
제공되는 XML 문서에 적용

를 (더 재미있게 만들 수있는 제삼자를 추가)
<root> 
    <person> 
     <id>1000</id> 
     <name>p1</name> 
    </person> 
    <person> 
     <id>1001</id> 
     <name>p2</name> 
    </person> 
    <person> 
     <id>1002</id> 
     <name>p3</name> 
    </person> 
    <rel> 
     <personid>1001</personid> 
     <personid>1000</personid> 
     <personid>1002</personid> 
    </rel> 
</root> 

이 원하는 정확한 결과를 생성합니다 :

person 2 is related to person 1 is related to person 3 
+0

내가 결국, 당신이 여기에서하고있는 것을 이해했을 때, Dimitre, 나는 밖으로 웃음을 터뜨렸다. 매우 영리하다. 초심자에게는 이것이 어떻게 작용하는지 분명하지 않다. - 내가 할 수있는 것보다 훨씬 더 당신의 솔루션을 설명 할 수있을 것이라고 확신한다. – Kevan

+0

Very clever 참으로 많은 요소와의 관계를 푸는 좋은 방법입니다. 그러나 match = text()가있는 마지막 템플릿이 무엇인지 잘 모르겠습니다. 감사! –

+0

@dan leadgy : 문서의 모든 텍스트 노드가 XSLT 처리 모델로 인해 출력되지 않도록 템플릿 -in 템플릿을 사용하면 XSLT 문서의 모든 텍스트 노드가 출력됩니다. –