2011-08-19 2 views
2

오래된 원본 XML :XSLT 다음 그룹

<Employees> 
    <Person> 
     <FirstName>Joy</FirstName> 
     <IsManager>N</IsManager> 
    </Person> 
    <Person> 
     <FirstName>Joyce</FirstName> 
     <IsManager>N</IsManager> 
    </Person> 
    <Person> 
     <FirstName>Joe</FirstName> 
     <IsManager>Y</IsManager> 
    </Person>... 
</Employees> 

새로운 소스 XML :

<Employees> 
     <Person> 
     <FirstName>Joy</FirstName> 
     <DetailsArray> 
      <Details1> 
      <IsManager>N</IsManager> 
      <IsSuperviser>N</IsSuperviser> 
      </Details1> 
     <Details2> 
       <IsManager>N</IsManager> 
      <IsSuperviser>N</IsSuperviser> 
      </Details2> 
     </DetailsArray> 
     </Person> 
     <Person> 
     <FirstName>Joyce</FirstName> 
     <DetailsArray> 
      <Details1> 
      <IsManager>N</IsManager> 
      <IsSuperviser>N</IsSuperviser> 
      </Details1> 
     <Details2> 
       <IsManager>N</IsManager> 
      <IsSuperviser>N</IsSuperviser> 
      </Details2> 
     </DetailsArray> 
     </Person> 
     <Person> 
     <FirstName>Joe</FirstName> 
     <DetailsArray> 
      <Details1> 
      <IsManager>N</IsManager> 
      <IsSuperviser>N</IsSuperviser> 
      </Details1> 
     <Details2> 
       <IsManager>Y</IsManager> 
      <IsSuperviser>N</IsSuperviser> 
      </Details2> 
    </DetailsArray> 
     </Person>... 
</Employees> 

출력해야한다 :

<Names> 
    <Name num='1'>Joe</Name> 
    <Name num='2'>Joy</Name> 
    <Name num='3'>Joyce</Name> 
    .... 
    </Names> 

이 소스 XML은 일부 조정이 이전 XML에 비해 . 여기에 새로운 조건이 "This person is 2projects or 2tasks"가 될 수 있습니다. 따라서 IsManager가 DetailsArray의 Details2 태그에서 'y'인 경우에도 IsManager = 'Y'인 사람부터 출력을 시작해야합니다. 결과물에 이름이 중복되어서는 안됩니다. 가정 해 동안 우리는 .. 이름이 중복 될 이전 답변을

감사합니다 ..

+1

질문의 텍스트가 다소 불분명합니다. 좀 더 이해하기 쉬울 수 있습니까? –

+0

"주기 출력"이란 무엇입니까? 위의 출력은 내가 아는 어떤 의미에서도 "순환"으로 보이지 않습니다. 또한 코드 시도를 보여 주면 귀하의 의도를 이해하는 데 도움이됩니다. – LarsH

+0

@LarsH - 물론 내 대답은 약간의 추측 이었지만 그의 출력이 주기적이라는 명백한 의미가 있습니다. 첫 번째 관리자에서 시작하여 모든 요소를 ​​순서대로 처리하고 첫 번째 관리자 앞에 모든 요소를 ​​가져 오기 위해 처음부터 다시 순환합니다. 내 대답은 분명히해야합니다. –

답변

2

편집를 정렬합니다. lwburk가 지적했듯이이 해답의 원래 솔루션은 노드를 IsManager으로 정렬합니다.

다음은 첫 번째 관리자를 찾아서 인쇄 한 다음 나머지 사람들을 순환시키는 솔루션입니다 (필요한 경우 처음부터 다시 순환).

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

<xsl:template match="Employees"> 

    <xsl:variable name="position" select="count(Person) - count(Person/IsManager[. = 'Y'][1]/../following-sibling::*)" /> 

    <xsl:call-template name="person"> 
     <xsl:with-param name="name" select="Person/IsManager[. = 'Y'][1]/../FirstName" /> 
     <xsl:with-param name="position" select="'1'" /> 
    </xsl:call-template> 

    <xsl:for-each select="Person[position() &gt; $position]">    
      <xsl:call-template name="person" /> 
    </xsl:for-each> 

    <xsl:for-each select="Person[position() &lt; $position]"> 
      <xsl:call-template name="person" /> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template name="person"> 
    <xsl:param name="name" select="FirstName" /> 
    <xsl:param name="position" select="position() + 1" /> 

    <Name> 
     <xsl:attribute name="num"><xsl:value-of select="$position" /></xsl:attribute> 
     <xsl:value-of select="$name" /> 
    </Name> 
</xsl:template> 

</xsl:stylesheet> 

올드 대답.

질문에 대해서는 확실하지 않지만, IsManager = Y으로 시작하는 사람의 이름을 모두 알고 싶습니다. <xsl:sort>IsManager 값으로 사용할 수 있습니다. "주문"속성에 "내림차순"을 지정하는 것을 잊지 마십시오 (그렇지 않으면 IsManager = Y을 가진 사람이 마지막 것입니다).

나는 당신의 입력 데이터와 함께 작동 예를 썼다 :

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

<xsl:template match="Employees"> 
    <xsl:for-each select="Person"> 
     <xsl:sort select="IsManager" order="descending" /> 

      <Name> 
       <xsl:attribute name="num"> 
        <xsl:value-of select="position()" /> 
       </xsl:attribute> 
       <xsl:value-of select="FirstName" /> 

      </Name> 

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

</xsl:stylesheet> 
+0

반대 투표는 없지만 그렇게 생각하지 않습니다. IsManager 플래그로 정렬합니다. 그는 첫 번째 매니저부터 시작하여 사이클을 찾고 있습니다. –

+0

@ lwburk : 답변을 업데이트했습니다. – Donovan

0

그것은 당신이 첫 번째 관리자에서 시작하려는 같은 소리하고 주위에 다시 순환 순서의 모든 Person 요소를 처리 파티션 요소 앞에 모든 요소를 ​​가져 오기 시작합니다.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="Employees/Person"/> 
    </xsl:template> 
    <xsl:template match="Person[IsManager='Y'][1]"> 
     <Name num="1"> 
      <xsl:apply-templates select="FirstName"/> 
     </Name> 
     <!-- partition --> 
     <xsl:apply-templates select="following-sibling::Person" mode="after"/> 
     <xsl:apply-templates select="../Person" mode="before"> 
      <xsl:with-param name="pos" select="last() - position() + 1"/> 
     </xsl:apply-templates> 
    </xsl:template> 
    <xsl:template match="Person" mode="after"> 
     <Name num="{position() + 1}"> 
      <xsl:apply-templates select="FirstName"/> 
     </Name> 
    </xsl:template> 
    <xsl:template match="Person[not(IsManager='Y') and 
       not(preceding-sibling::Person[IsManager='Y'])]" mode="before"> 
     <xsl:param name="pos" select="0"/> 
     <Name num="{position() + $pos}"> 
      <xsl:apply-templates select="FirstName"/> 
     </Name> 
    </xsl:template> 
    <xsl:template match="Person"/> 
    <xsl:template match="Person" mode="before"/> 
</xsl:stylesheet> 

참고 :

다음 스타일은 원하는 결과를 달성 1) 용액이 소스에 존재할 적어도 하나의 관리자가 요구하는 단계; 2) 다중 패스가 필요하고 그룹 구성원을 테스트하기 위해 preceding-sibling을 사용하기 때문에 (파티션 요소 앞에있는 요소의 경우) 매우 효율적인 솔루션이 아닐 수도 있습니다.

예 입력 :

<Employees> 
    <Person> 
     <FirstName>Joy</FirstName> 
     <IsManager>N</IsManager> 
    </Person> 
    <Person> 
     <FirstName>Joyce</FirstName> 
     <IsManager>N</IsManager> 
    </Person> 
    <Person> 
     <FirstName>Joe</FirstName> 
     <IsManager>Y</IsManager> 
    </Person> 
    <Person> 
     <FirstName>Professor X</FirstName> 
     <IsManager>N</IsManager> 
    </Person> 
    <Person> 
     <FirstName>Songey</FirstName> 
     <IsManager>Y</IsManager> 
    </Person> 
</Employees> 

출력 :

<Name num="1">Joe</Name> 
<Name num="2">Professor X</Name> 
<Name num="3">Songey</Name> 
<Name num="4">Joy</Name> 
<Name num="5">Joyce</Name> 
1

이 짧고 간단 변환 (NO 모드 변수없이, 오직 세 템플릿)

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

<xsl:template match="/"> 
    <Names> 
    <xsl:apply-templates select="*/Person[IsManager='Y'][1]"/> 
    </Names> 
</xsl:template>  

<xsl:template match="Person[IsManager='Y']"> 
    <xsl:apply-templates select= 
    "FirstName |../Person[not(generate-id()=generate-id(current()))] 
       /FirstName 
    "> 
    <xsl:sort select= 
    "generate-id(..) = generate-id(/*/*[IsManager = 'Y'][1])" 
    order="descending"/> 
    <xsl:sort select= 
    "boolean(../preceding-sibling::Person[IsManager='Y'])" 
    order="descending"/> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template match="FirstName"> 
    <Name num="{position()}"><xsl:value-of select="."/></Name> 
</xsl:template> 
</xsl:stylesheet> 

다음 X에 적용하면 ML (@lwburk 의해 제공되는 것과 동일)

<Names> 
    <Name num="1">Joe</Name> 
    <Name num="2">Professor X</Name> 
    <Name num="3">Songey</Name> 
    <Name num="4">Joy</Name> 
    <Name num="5">Joyce</Name> 
</Names> 

설명 :

  1. 이것이이다

    <Employees> 
        <Person> 
         <FirstName>Joy</FirstName> 
         <IsManager>N</IsManager> 
        </Person> 
        <Person> 
         <FirstName>Joyce</FirstName> 
         <IsManager>N</IsManager> 
        </Person> 
        <Person> 
         <FirstName>Joe</FirstName> 
         <IsManager>Y</IsManager> 
        </Person> 
        <Person> 
         <FirstName>Professor X</FirstName> 
         <IsManager>N</IsManager> 
        </Person> 
        <Person> 
         <FirstName>Songey</FirstName> 
         <IsManager>Y</IsManager> 
        </Person> 
    </Employees> 
    

    가 원하는 정확한 결과 생산 여러 키를 사용하여 정렬하는 일반적인 경우

  2. 가장 우선 순위가 높은 정렬 기준은 사람 부모가 첫 번째 관리자인지 여부입니다.

  3. 두 번째 우선 순위 정렬 기준은 상위 Person이 관리자를 따르고 있는지 여부입니다.

  4. 부울 정렬시 false()true() 앞에 오면 내림차순으로 정렬 된 노드 목록을 처리한다는 사실을 이용합니다.

+0

IsManager = Y 인 Person이 없을 때 실패합니다 (이 경우 솔루션도 실패합니다.) 관리자가 없을 때 "Persons"를 순환 시키면 매우 좋은 해결책이됩니다 – Donovan

+0

@Alberteddu : ** 문제는 관리자가 적어도 한 명은 있다고 가정합니다 ** 관리자가 없을 수도 있고 그러한 입력을 위해 생성 할 출력을 가정하지 않는다는 것을 언급하지 않습니다.저는이 새로운 요구 사항이 당신의 상상력에 기인한다고 생각합니다. 그러나 상상력은 다릅니다. –

+1

정확하고 정확한 요구 사항 목록에 상관없이 제안 된 솔루션으로 인해 발생할 수있는 문제를 고려하여 자세하게 대응할 수없는 충동입니다. 영업 이익. 어떤 종류의 개인적인 도전처럼 :) 그렇습니다. 아마 우리는 다른 상상력을 가지고있을 것입니다. – Donovan