2016-01-04 35 views
0

我有一個示例消息,必須使用XSLT將其轉換爲不同的輸出結構。在XSLT中處理多個條件循環

傳入消息是

<document> 
    <ObjectId> 
    <ID>1000909090</ID> 
    <dlex> 
     <attrGroupMany name="streetinfo"> 
      <row>            <!-- Mandatory Loop --> 
       <attr name="streetcode">AS_DRAINED</attr> 
       <attrQualMany name="streetintake">    <!-- Optional Loop --> 
        <value qual="en">dvif1</value> 
        <value qual="nl">dvif2</value> 
       </attrQualMany> 
       <attr name="streettype">BY_MEASURE</attr> 
       <attrQual name="streetbasis" qual="ONZ">5</attrQual> 
       <attrQual name="streetsize" qual="EA">1</attrQual> 
       <attrQualMany name="streetsizeDescription"> <!-- Optional Loop --> 
        <value qual="en">sz1</value> 
        <value qual="hi">sz2</value> 
       </attrQualMany> 
       <attrGroupMany name="streetDetails"> 
        <row>          <!-- Optional Loop --> 
         <attr name="streetTypeCode">FAT</attr> 
         <attr name="streetValueIntakePercent">25</attr> 
         <attr name="streetPrecisionCode">APPROXIMATELY</attr> 
         <attrQualMany name="streetContained"> <!-- Optional Loop --> 
          <value qual="ONZ">2</value> 
          <value qual="OZA">3</value> 
         </attrQualMany> 
        </row> 
        <row> 
         <attr name="streetTypeCode">FAMS</attr> 
         <attr name="streetValueIntakePercent">999</attr> 
         <attr name="streetPrecisionCode">EXACT</attr> 
         <attrQualMany name="streetContained"> 
          <value qual="ONZ">4</value> 
          <value qual="OZA">5</value> 
         </attrQualMany> 
        </row> 
       </attrGroupMany> 
      </row> 
     </attrGroupMany> 
    </dlex> 
</ObjectId> 
</document> 

輸出消息是

<?xml version="1.0" encoding="UTF-8"?> 
<CatalogObjectId> 
<RelationshipData> 
    <Relationship> 
    <RelationType>ObjectId_Street</RelationType> 
    <RelatedObjectIds> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAT-2-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAT-3-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAMS-4-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAMS-5-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAT-2-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAT-3-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAMS-4-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAMS-5-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAT-2-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAT-3-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAMS-4-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAMS-5-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAT-2-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAT-3-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAMS-4-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAMS-5-OZA" /> 
    </RelatedObjectIds> 
    </Relationship> 
</RelationshipData> 
</CatalogObjectId> 

這是正常使用時,我們使用下面的XSLT。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="xml" indent="yes" /> 
<xsl:template match="document"> 
    <CatalogObjectId> 
     <RelationshipData> 
      <Relationship> 
       <RelationType>ObjectId_Street</RelationType> 
       <RelatedObjectIds> 
        <xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']/row"> 
         <xsl:variable name="v_position_streetinfo" select="position()" />             
         <xsl:variable name="v_streetcode"> 
          <xsl:value-of select="attr[@name='streetcode'])"/> 
         </xsl:variable>     
         <xsl:variable name="v_streetintake" select="attrQualMany[@name = 'streetintake']/value" /> 
         <xsl:variable name="v_streetsizeDescription" select="attrQualMany[@name = 'streetsizeDescription']/value" /> 
         <xsl:variable name="v_streetDetails" select="attrGroupMany[@name = 'streetDetails']/row" />       
         <xsl:for-each select="$v_streetintake"> 
          <xsl:variable name="v_streetintakevalue" select="." /> 
          <xsl:variable name="v_streetintakequal" select="./@qual" /> 
          <xsl:for-each select="$v_streetsizeDescription"> 
           <xsl:variable name="v_streetsizeDescriptionvalue" select="." /> 
           <xsl:variable name="v_streetsizeDescriptionqual" select="./@qual" /> 
           <xsl:for-each select="$v_streetDetails"> 
            <xsl:variable name="v_streetTypeCode"> 
             <xsl:value-of select="attr[@name='streetTypeCode'])"/> 
            </xsl:variable> 
            <xsl:variable name="v_streetContained" select="attrQualMany[@name = 'streetContained']/value" /> 
            <xsl:for-each select="$v_streetContained"> 
             <xsl:variable name="v_streetContainedvalue" select="." /> 
             <xsl:variable name="v_streetContainedqual" select="./@qual" /> 
             <RelatedObjectId> 
              <xsl:attribute name="referenceKey">                  
               <xsl:value-of select="concat('ObjectId_Street','-',$v_position_streetinfo,'-',$v_streetcode,'-',$v_streetintakevalue,'-',$v_streetintakequal,'-',$v_streetsizeDescriptionvalue,'-',$v_streetsizeDescriptionqual,'-',$v_streetTypeCode,'-',$v_streetContainedvalue,'-',$v_streetContainedqual)"/>       
              </xsl:attribute>     
             </RelatedObjectId> 
            </xsl:for-each> 
           </xsl:for-each> 
          </xsl:for-each> 
         </xsl:for-each> 
        </xsl:for-each> 
       </RelatedObjectIds> 
      </Relationship> 
     </RelationshipData> 
    </CatalogObjectId> 
</xsl:template> 
</xsl:stylesheet> 

但是,當任何可選循環中的任何一個不來時,它不起作用。當所有可選的循環都存在時,我寫了XSLT,當任何1或2或3或者沒有任何可選組進入消息時,如何編寫XSLT。麻煩推薦

預期輸出

當第一任選組不存在時,將有8個記錄中的輸出。

<?xml version="1.0" encoding="UTF-8"?> 
<CatalogObjectId> 
    <RelationshipData> 
    <Relationship> 
    <RelationType>ObjectId_Street</RelationType> 
    <RelatedObjectIds> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAT-2-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAT-3-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAMS-4-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAMS-5-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAT-2-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAT-3-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAMS-4-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAMS-5-OZA" /> 
    </RelatedObjectIds> 
    </Relationship> 
</RelationshipData> 
</CatalogObjectId> 

當第一個和第二個可選組不存在時,輸出中將有4個記錄。

<?xml version="1.0" encoding="UTF-8"?> 
<CatalogObjectId> 
<RelationshipData> 
    <Relationship> 
    <RelationType>ObjectId_Street</RelationType> 
    <RelatedObjectIds> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAT-2-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAT-3-OZA" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAMS-4-ONZ" /> 
     <RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAMS-5-OZA" /> 
    </RelatedObjectIds> 
    </Relationship> 
</RelationshipData> 
</CatalogObjectId> 
+0

當可選不存在時,您的預期產出是多少? –

+0

我已添加 – Victor

回答

1

好的。我不確定我完全理解您的預期輸出。您的示例列出了4個可選循環,而不是兩個,我不確定示例輸出中帶有缺失組的「e​​n」來自哪裏。

但是,這可以讓你開始。我沒有試圖在嵌套的for-each結構中彙總所有內容,而是在類似於遞歸下降解析器的結構中使用了多個模板。在每個級別,代碼檢查可選元素,並在其周圍循環,或跳到下一級。 referenceKey字符串作爲參數傳遞,並在我們向下移動時構建。

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

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/document"> 
     <CatalogObjectId> 
      <RelationshipData> 
       <Relationship> 
        <RelationType>ObjectId_Street</RelationType> 
        <RelatedObjectIds> 
         <xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']"> 
          <xsl:variable name="pos" select="position()"/> 
          <xsl:apply-templates select="row" mode="streetintake"> 
           <xsl:with-param name="referenceKey" select="concat('ObjectId_Street-',$pos)" /> 
          </xsl:apply-templates> 
         </xsl:for-each> 
        </RelatedObjectIds> 
       </Relationship> 
      </RelationshipData> 
     </CatalogObjectId> 
    </xsl:template> 

    <xsl:template match="row" mode="streetintake"> 
     <xsl:param name="referenceKey" /> 
     <xsl:variable name="streetcode" select="concat($referenceKey,'-',attr[@name='streetcode'],'-')"/> 
     <xsl:choose> 
      <xsl:when test="attrQualMany[@name='streetintake']/value"> 
       <xsl:for-each select="attrQualMany[@name='streetintake']/value"> 
        <xsl:apply-templates select="../.." mode="streetsize"> 
         <xsl:with-param name="referenceKey" select="concat($streetcode,text(),'-',@qual)" /> 
        </xsl:apply-templates> 
       </xsl:for-each> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:apply-templates select="." mode="streetsize"> 
        <xsl:with-param name="referenceKey" select="$streetcode" /> 
       </xsl:apply-templates> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <xsl:template match="row" mode="streetsize"> 
     <xsl:param name="referenceKey" /> 
     <xsl:choose> 
      <xsl:when test="attrQualMany[@name='streetsizeDescription']/value"> 
       <xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value"> 
        <xsl:apply-templates select="../../attrGroupMany[@name='streetDetails']" mode="streetdetails"> 
         <xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" /> 
        </xsl:apply-templates> 
       </xsl:for-each> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:apply-templates select="attrGroupMany[@name='streetDetails']" mode="streetdetails"> 
        <xsl:with-param name="referenceKey" select="$referenceKey" /> 
       </xsl:apply-templates> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <xsl:template match="attrGroupMany" mode="streetdetails"> 
     <xsl:param name="referenceKey" /> 
     <xsl:choose> 
      <xsl:when test="row"> 
       <xsl:apply-templates select="row" mode="streetdetails"> 
        <xsl:with-param name="referenceKey" select="concat($referenceKey,'-',row/attr[@name='streetTypeCode'])" /> 
       </xsl:apply-templates> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="RelatedObjectId"> 
        <xsl:with-param name="referenceKey" select="$referenceKey" /> 
       </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose>   
    </xsl:template> 

    <xsl:template match="row" mode="streetdetails"> 
     <xsl:param name="referenceKey" /> 
     <xsl:choose> 
      <xsl:when test="attrQualMany[@name='streetContained']"> 
       <xsl:apply-templates select="attrQualMany[@name='streetContained']"> 
        <xsl:with-param name="referenceKey" select="$referenceKey"/> 
       </xsl:apply-templates> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="RelatedObjectId"> 
        <xsl:with-param name="referenceKey" select="$referenceKey" /> 
       </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose>   
    </xsl:template> 

    <xsl:template match="attrQualMany[@name='streetContained']"> 
     <xsl:param name="referenceKey" /> 
     <xsl:choose> 
      <xsl:when test="value"> 
       <xsl:for-each select="value"> 
        <xsl:call-template name="RelatedObjectId"> 
         <xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" /> 
        </xsl:call-template> 
       </xsl:for-each> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="RelatedObjectId"> 
        <xsl:with-param name="referenceKey" select="$referenceKey" /> 
       </xsl:call-template>     
      </xsl:otherwise> 
     </xsl:choose>   
    </xsl:template> 

    <xsl:template name="RelatedObjectId"> 
     <xsl:param name="referenceKey" /> 
     <RelatedObjectId> 
      <xsl:attribute name="referenceKey"><xsl:value-of select="$referenceKey"/></xsl:attribute> 
     </RelatedObjectId>   
    </xsl:template> 

</xsl:stylesheet> 
0

我加入了幾個片段,以現有的代碼來處理時,所有的可選組缺少空的場景時,或者當完成

<attrGroupMany name="streetDetails"> details are missing. 

<xsl:output method="xml" indent="yes"/> 

<xsl:template match="/document"> 
    <CatalogObjectId> 
     <RelationshipData> 
      <Relationship> 
       <RelationType>ObjectId_Street</RelationType> 
       <RelatedObjectIds> 
        <xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']"> 
         <xsl:variable name="pos" select="position()"/> 
         <xsl:apply-templates select="row" mode="streetintake"> 
          <xsl:with-param name="referenceKey" select="concat('ObjectId_Street-',$pos)" /> 
         </xsl:apply-templates> 
        </xsl:for-each> 
       </RelatedObjectIds> 
      </Relationship> 
     </RelationshipData> 
    </CatalogObjectId> 
</xsl:template> 

<xsl:template match="row" mode="streetintake"> 
    <xsl:param name="referenceKey" /> 
    <xsl:variable name="streetcode" select="concat($referenceKey,'-',attr[@name='streetcode'],'-')"/> 
    <xsl:choose> 
     <xsl:when test="attrQualMany[@name='streetintake']/value"> 
      <xsl:for-each select="attrQualMany[@name='streetintake']/value"> 
       <xsl:apply-templates select="../.." mode="streetsize"> 
        <xsl:with-param name="referenceKey" select="concat($streetcode,text(),'-',@qual)" /> 
       </xsl:apply-templates> 
      </xsl:for-each> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates select="." mode="streetsize"> 
       <xsl:with-param name="referenceKey" select="$streetcode" /> 
      </xsl:apply-templates> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template match="row" mode="streetsize"> 
    <xsl:param name="referenceKey" /> 
    <xsl:choose> 
     <xsl:when test="attrQualMany[@name='streetsizeDescription']/value"> 
      <xsl:choose> 
       <xsl:when test="attrGroupMany[@name='streetDetails']"> 
        <xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value"> 
         <xsl:apply-templates select="../../attrGroupMany[@name='streetDetails']" mode="streetdetails"> 
          <xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" /> 
         </xsl:apply-templates> 
        </xsl:for-each> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value"> 
         <xsl:call-template name="RelatedObjectId"> 
          <xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" /> 
         </xsl:call-template> 
        </xsl:for-each> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:if test="not(attrQualMany[@name='streetintake']) and not(attrQualMany[@name='streetsizeDescription']) and not(attrGroupMany[@name='streetDetails'])"> 
       <xsl:call-template name="RelatedObjectId"> 
        <xsl:with-param name="referenceKey" select="$referenceKey" /> 
       </xsl:call-template>     
      </xsl:if> 
      <xsl:apply-templates select="attrGroupMany[@name='streetDetails']" mode="streetdetails"> 
       <xsl:with-param name="referenceKey" select="$referenceKey" /> 
      </xsl:apply-templates> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template match="attrGroupMany" mode="streetdetails"> 
    <xsl:param name="referenceKey" /> 
    <xsl:choose> 
     <xsl:when test="row"> 
      <xsl:apply-templates select="row" mode="streetdetails"> 
       <xsl:with-param name="referenceKey" select="concat($referenceKey,'-',row/attr[@name='streetTypeCode'])" /> 
      </xsl:apply-templates> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:call-template name="RelatedObjectId"> 
       <xsl:with-param name="referenceKey" select="$referenceKey" /> 
      </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose>   
</xsl:template> 

<xsl:template match="row" mode="streetdetails"> 
    <xsl:param name="referenceKey" /> 
    <xsl:choose> 
     <xsl:when test="attrQualMany[@name='streetContained']"> 
      <xsl:apply-templates select="attrQualMany[@name='streetContained']"> 
       <xsl:with-param name="referenceKey" select="$referenceKey"/> 
      </xsl:apply-templates> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:call-template name="RelatedObjectId"> 
       <xsl:with-param name="referenceKey" select="$referenceKey" /> 
      </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose>   
</xsl:template> 

<xsl:template match="attrQualMany[@name='streetContained']"> 
    <xsl:param name="referenceKey" /> 
    <xsl:choose> 
     <xsl:when test="value"> 
      <xsl:for-each select="value"> 
       <xsl:call-template name="RelatedObjectId"> 
        <xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" /> 
       </xsl:call-template> 
      </xsl:for-each> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:call-template name="RelatedObjectId"> 
       <xsl:with-param name="referenceKey" select="$referenceKey" /> 
      </xsl:call-template>     
     </xsl:otherwise> 
    </xsl:choose>   
</xsl:template> 

<xsl:template name="RelatedObjectId"> 
    <xsl:param name="referenceKey" /> 
    <RelatedObjectId> 
     <xsl:attribute name="referenceKey"> 
      <xsl:value-of select="$referenceKey"/> 
     </xsl:attribute> 
    </RelatedObjectId>   
</xsl:template>