2017-05-08 55 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="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> 

我使用下面的樣式表文件:

<?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> 

我需要每個輸出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元素使用的@sequence,而不是比較for-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的學生非常有幫助!這個網站是一個生活救星。 Ralph B –