2010-07-06 3 views
4

클래스에 동일한 성을 가진 모든 학생이 있는지 확인하는 XSL 스 니펫을 생각하려고합니다. 예, 그럼 (비슷한 것을하십시오) print "모든 lastnames는 동일합니다"else print "모든 lastnames가 동일하지 않습니다".XSLT : 특정 노드가 하나의 부모에서 모두 같은지 확인하는 방법

실제로 무엇을 인쇄해도 상관 없습니다. 나는 단지 그것에 대한 올바른 논리를 찾으려고 노력하고있다.

<root> 
    <class name="Physics"> 
     <student> 
      <firstname>John</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Mary</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Ralph</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
    </class> 
    <class name="Math"> 
     <student> 
      <firstname>John</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Mary</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Tee</firstname> 
      <lastname>Rex</lastname> 
      <age>21</age> 
     </student> 
    </class> 
</root> 

따라서, 물리학 클래스는 "모든 라스트 네임이 동일하다"인쇄 것입니다 :

여기 내 샘플 XML입니다. 수학 수업에서는 "모든 성이 동일하지 않습니다"라고 인쇄합니다.

(이 작은 문제에 환원 할 수없는 때문에이 내 진짜 XML하지, 그래서 대신 내가 정의 내 문제 표현하기 위해 XML을했다) 어떤 도움이 크게 감사합니다

합니다.

관련, Shobhit

+0

좋은 질문 (+1). 효율적인 해결책은 내 대답을 참조하십시오. :) –

+0

여러분의 솔루션에 대한 감사드립니다. 나는 Tomalak의 접근법을 사용하여 끝냈다. 다른 접근법도 좋지만 Tomalak의 솔루션은 이해하기 쉽고 사용하기 쉽습니다. – bits

답변

4

흠. 당신의 문제에 대해 아무 것도 아는하지, 내가 이런 짓을 했을까 :

<xsl:template match="class"> 
    <xsl:choose> 
    <xsl:when test=" 
     count(student[not(lastname = preceding-sibling::student/lastname)]) = 1 
    "> 
     <xsl:text>all lastnames are same</xsl:text> 
    <xsl:when> 
    <xsl:otherwise> 
     <xsl:text>all lastnames are not same</xsl:text> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

XPath 식은

student[not(lastname = preceding-sibling::student/lastname)] 

누구 <lastname> 같은 클래스 내에서 항 LASTNAME 달리 모든 <student> 노드를 선택합니다.

모든 동일한 성을 가진 클래스에서, 첫 번째 학생의 성은 이전 성과는 달리 항상 있기 때문에 카운트는 정확히 1입니다. 카운트가 1보다 높으면, 그 클래스의 일부 학생들은 다른 성을가집니다.

위의 논리에서 클래스에 학생이 전혀없는 경우는 <xsl:otherwise>으로 인식됩니다. 이 경우를 명시 적으로 처리하는 것이 좋습니다.

2

이 스타일 :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="student"/> 
    <xsl:template match="student[1]">all lastnames are same</xsl:template> 
    <xsl:template match="student[1][lastname != ../student/lastname]" priority="1">all lastnames are not same</xsl:template> 
</xsl:stylesheet> 

결과 :

<root> 
    <class name="Physics">all lastnames are same</class> 
    <class name="Math">all lastnames are not same</class> 
</root> 

참고 : 노드 세트 비교.

편집 : @name.

편집 2 : 콤팩트. 오류 복구를 방지하기 위해 @ 우선 순위를 참고하십시오.

1

이 변환 :

All names are not the same. 

는 훨씬 더 효율적이 변화를 만드는 키의 사용을주의 마십시오 제공된 XML 문서에 적용

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my" 
> 
<xsl:output method="text"/> 

<xsl:key name="kstudentByName" 
    match="student" use="lastname"/> 

<my:text> 
    <text> not </text> 
</my:text> 

<xsl:variable name="vText" select="document('')/*/my:text/*"/> 

<xsl:template match="/"> 
    <xsl:variable name="vNumNames" select= 
    "count(*/*/student[generate-id() 
        = 
         generate-id(key('kstudentByName', lastname)[1]) 
        ] 
     ) 

     > 1 
    "/> 

    All names are <xsl:value-of select="$vText[$vNumNames]"/> the same. 
</xsl:template> 
</xsl:stylesheet> 

올바른 결과를 생성보다 각각의 이름을 모든 이전 형제의 이름과 비교하는 시간 복잡도가

관련 문제