2017-05-08 7 views
0

나는 다음과 같은 XML 소스 파일이 있습니다만들기 출력 그룹

나는 세 그룹 세 가지 입력 그룹에서 모든 요소의 독특한 세트를 포함하는 각 구성 출력 파일을 작성해야
<?xml version = "1.0" encoding = "UTF-8"?> 
<Master revision="B" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Data> 
     <Block name="PRIMARY" > 
      <BlockGroup name="GROUP_PRIMARY" > 
       <BlockLayer Name="COVER" sequence="1"> 
        <BlockRef id="BLOCK_COVER"/> 
       </BlockLayer> 
       <BlockLayer Name="TOP" sequence="2"> 
        <BlockRef id="BLOCK_TOP"/> 
       </BlockLayer> 
       <BlockLayer Name="INDEX_3" sequence="3"> 
        <BlockRef id="BLOCK_INDEX_3"/> 
       </BlockLayer> 
       <BlockLayer Name="INT2" sequence="4"> 
        <BlockRef id="BLOCK_INT2"/> 
       </BlockLayer> 
      </BlockGroup> 
     </Block> 
     <Block name="SECONDARY" > 
      <BlockGroup name="GROUP_SECONDARY" > 
       <BlockLayer Name="BLOCK_TOP" sequence="5"> 
        <BlockRef id="BLOCK_TOP"/> 
       </BlockLayer> 
       <BlockLayer Name="INT6" sequence="6"> 
        <BlockRef id="BLOCK_INT6"/> 
       </BlockLayer> 
       <BlockLayer Name="INDEX_7" sequence="7"> 
        <BlockRef id="BLOCK_INDEX_7"/> 
       </BlockLayer> 
      </BlockGroup> 
     </Block> 
     <Block name="TERTIARY"> 
      <BlockGroup name="GROUP_TERTIARY"> 
       <BlockLayer Name="COVER" sequence="1"> 
        <BlockRef id="BLOCK_COVER"/> 
       </BlockLayer> 
       <BlockLayer Name="TOP" sequence="2"> 
        <BlockRef id="BLOCK_TOP"/> 
       </BlockLayer> 
       <BlockLayer Name="INDEX_3" sequence="3"> 
        <BlockRef id="BLOCK_INDEX_3"/> 
       </BlockLayer> 
       <BlockLayer Name="INT2" sequence="4"> 
        <BlockRef id="BLOCK_INT2"/> 
       </BlockLayer> 
      </BlockGroup> 
     </Block> 
    </Data> 
</Master> 

, 과 같이 : 내가 필요

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <Blocks> 
      <xsl:apply-templates select="/Master/Data/Block" mode="block"/> 
     </Blocks> 
    </xsl:template> 

    <xsl:template match="/Master/Data/Block" mode="block"> 
     <Block Name="{@name}" > 
      <BlockNumber><xsl:value-of select="position()" /></BlockNumber> 
      <BlockCollection> 
       <xsl:apply-templates select="/Master/Data/Block/BlockGroup/BlockLayer[not(@sequence = preceding::*/@sequence)]"> 
        <xsl:sort select="@sequence" data-type="number"/> 
       </xsl:apply-templates> 
      </BlockCollection> 
     </Block> 
    </xsl:template> 

    <xsl:template match="/Master/Data/Block/BlockGroup/BlockLayer"> 
     <BlockLayer Name="{@Name}" Order="{@sequence}"> 
      <Display> 
       <xsl:value-of select="if(count(../../preceding-sibling::Block) = 0) then 'True' else 'False'"/> 
      </Display> 
     </BlockLayer> 
    </xsl:template> 

</xsl:stylesheet> 

:

<?xml version="1.0" encoding="UTF-8"?> 
<Blocks> 
    <Block Name="PRIMARY"> 
     <BlockNumber>1</BlockNumber> 
     <BlockCollection> 
     <BlockLayer Name="COVER" Order="1"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="TOP" Order="2"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="INDEX_3" Order="3"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="INT2" Order="4"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="BLOCK_TOP" Order="5"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="INT6" Order="6"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="INDEX_7" Order="7"> 
      <Display>False</Display> 
     </BlockLayer> 
     </BlockCollection> 
    </Block> 
    <Block Name="SECONDARY"> 
     <BlockNumber>2</BlockNumber> 
    <BlockCollection> 
     <BlockLayer Name="COVER" Order="1"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="TOP" Order="2"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="INDEX_3" Order="3"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="INT2" Order="4"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="BLOCK_TOP" Order="5"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="INT6" Order="6"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="INDEX_7" Order="7"> 
      <Display>True</Display> 
     </BlockLayer> 
     </BlockCollection> 
    </Block> 
    <Block Name="TERTIARY"> 
     <BlockNumber>3</BlockNumber> 
     <BlockCollection> 
     <BlockLayer Name="COVER" Order="1"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="TOP" Order="2"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="INDEX_3" Order="3"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="INT2" Order="4"> 
      <Display>True</Display> 
     </BlockLayer> 
     <BlockLayer Name="BLOCK_TOP" Order="5"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="INT6" Order="6"> 
      <Display>False</Display> 
     </BlockLayer> 
     <BlockLayer Name="INDEX_7" Order="7"> 
      <Display>False</Display> 
     </BlockLayer> 
     </BlockCollection> 
    </Block> 
</Blocks> 

나는 다음과 같은 스타일 시트 파일을 사용하고 있습니다 각 출력 BlockLayer 요소의 Display 요소가 True 또는 False를 표시하여 해당 입력 그룹이 속하는 세 입력 그룹을 나타냅니다. 따라서 BlockLayers 1, 2, 3, 4는 True를 표시하고 BlockLayers 5, 6, 7은 첫 번째 및 세 번째 그룹에 대해 False를 표시합니다.

두 번째 그룹의 경우 BlockLayers 1, 2, 3, 4는 False를 표시하고 5, 6, 7은 True를 표시해야합니다.

내 첫 번째 시도는 표현 사용

<xsl:value-of select="if(count(../../preceding-sibling::Block) = 0) then 'True' else 'False'"/> 

컨텍스트가 BlockLayer 수준입니다 그리고 각 BlockLayer의 조부모가 필요합니다. 이 표현식은 분명히 첫 번째 그룹의 BlockLayers 만 표시 할 수 있습니다. 각 입력 그룹에서 BlockLayer가 있는지 어떻게 확인할 수 있습니까? (너무 많은 세부 사항이 아니다 희망 ...)

안부,

랄프 브라이스는

답변

0

나는 preceding 요소 대신 비교의 @sequencefor-each-group을 사용하는 것이 좋습니다 생각 그룹을 가지고 있고 현재의 요소와 교차하는지 비교할 수 있습니다 Block :

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <Blocks> 
      <xsl:apply-templates select="/Master/Data/Block"/> 
     </Blocks> 
    </xsl:template> 

    <xsl:template match="/Master/Data/Block"> 
     <Block Name="{@name}"> 
      <xsl:variable name="Block" select="."/> 
      <BlockNumber><xsl:value-of select="position()" /></BlockNumber> 
      <BlockCollection> 
       <xsl:for-each-group select="/Master/Data/Block/BlockGroup/BlockLayer" group-by="xs:integer(@sequence)"> 
        <xsl:sort select="current-grouping-key()"/> 
        <xsl:apply-templates select="."> 
         <xsl:with-param name="Display" select="boolean(current-group() intersect $Block/BlockGroup/BlockLayer)"/> 
        </xsl:apply-templates> 
       </xsl:for-each-group> 
      </BlockCollection> 
     </Block> 
    </xsl:template> 

    <xsl:template match="/Master/Data/Block/BlockGroup/BlockLayer"> 
     <xsl:param name="Display"/> 
     <BlockLayer Name="{@Name}" Order="{@sequence}"> 
      <Display> 
       <xsl:value-of select="$Display"/> 
      </Display> 
     </BlockLayer> 
    </xsl:template> 

</xsl:stylesheet> 

온라인 http://xsltransform.net/93dEHFC에서 왼쪽 작업은 true/false 대신 True/False을 사용하는 것입니다.

+0

우수 - 완벽하게 작동합니다! 고맙습니다, 마틴. –

+0

@RalphB, 문제가 해결되면 답변 수령을 고려하십시오. 그 방법에 대한 자세한 내용은 http://stackoverflow.com/help/accepted-answer를 참조하십시오. –

+0

사과! 나는 당신의 우수한 대답을 받아 들였습니다. 그들은 내 문제를 해결했을뿐만 아니라 연구 방향을 지적 해주었습니다. XSLT 학생에게 매우 도움이되었습니다! 이 사이트는 생명의 은인입니다. 랄프 B –