将两个xsl文件的功能合并到一个文件中(续.....)

时间:2011-01-10 11:30:11

标签: xslt xslt-1.0

这是我的问题的继续:

Merge functionality of two xsl files into a single file (not a xsl import or include issue)


我必须将上述问题的解决方案(xsl)合并到以下xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">

 <xsl:template match="/">
    <Declaration>
      <Message>
        <Meduim>
          <xsl:value-of select="/Declaration/Message/Meduim"/>
        </Meduim>
        <MessageIdentifier>
          <xsl:value-of select="/Declaration/Message/MessageIdentifier"/>
        </MessageIdentifier>
        <ControlingAgencyCode>
          <xsl:value-of select="/Declaration/Message/ControlingAgencyCode"/>
        </ControlingAgencyCode>
        <AssociationAssignedCode>
          <xsl:value-of select="/Declaration/Message/AssociationAssignedCode"/>
        </AssociationAssignedCode>
        <CommonAccessReference>
          <xsl:value-of select="/Declaration/Message/CommonAccessReference"/>
        </CommonAccessReference>
      </Message>
      <BeginingOfMessage>
        <MessageCode>
          <xsl:value-of select="/Declaration/BeginingOfMessage/MessageCode"/>
        </MessageCode>
        <DeclarationCurrency>
          <xsl:value-of select="/Declaration/BeginingOfMessage/DeclarationCurrency"/>
        </DeclarationCurrency>
        <MessageFunction>
          <xsl:value-of select="/Declaration/BeginingOfMessage/MessageFunction"/>
        </MessageFunction>
      </BeginingOfMessage>
      <Header>
        <ProcessingInformation>
          <xsl:for-each select="/Declaration/Header/ProcessingInformation/ProcessingInstructions">
            <ProcessingInstructions>
              <xsl:value-of select="."/>
            </ProcessingInstructions>
          </xsl:for-each>
        </ProcessingInformation>
        <xsl:for-each select="/Declaration/Header/Seal">
          <Seal>
            <SealID>
              <xsl:value-of select="SealID"/>
            </SealID>
            <SealLanguage>
              <xsl:value-of select="SealLanguage"/>
            </SealLanguage>
          </Seal>
        </xsl:for-each>
          <xsl:choose>
          <xsl:when test='/Declaration/Header/DeclarantsReference = ""'>
            <DeclarantsReference>
              <xsl:text disable-output-escaping="no">A</xsl:text>
            </DeclarantsReference>
          </xsl:when>
          <xsl:otherwise>
            <DeclarantsReference>
              <xsl:value-of select="/Declaration/Header/DeclarantsReference"/>
            </DeclarantsReference>
          </xsl:otherwise>
        </xsl:choose>
        <xsl:for-each select="/Declaration/Header/Items">
          <Items>
            <CustomsStatusOfGoods>
              <CPC>
                <xsl:value-of select="CustomsStatusOfGoods/CPC"/>
              </CPC>
              <CommodityCode>
                <xsl:value-of select="CustomsStatusOfGoods/CommodityCode"/>
              </CommodityCode>
              <ECSuplementaryMeasureCode1>
                <xsl:value-of select="CustomsStatusOfGoods/ECSuplementaryMeasureCode1"/>
              </ECSuplementaryMeasureCode1>
              <ECSuplementaryMeasureCode2>
                <xsl:value-of select="CustomsStatusOfGoods/ECSuplementaryMeasureCode2"/>
              </ECSuplementaryMeasureCode2>
              <PreferenceCode>
                <xsl:value-of select="CustomsStatusOfGoods/PreferenceCode"/>
              </PreferenceCode>
            </CustomsStatusOfGoods>
            <xsl:for-each select="ItemAI">
              <ItemAI>
                <AICode>
                  <xsl:value-of select="AICode"/>
                </AICode>
                <AIStatement>
                  <xsl:value-of select="AIStatement"/>
                </AIStatement>
                <AILanguage>
                  <xsl:value-of select="AILanguage"/>
                </AILanguage>
              </ItemAI>
            </xsl:for-each>
            <Locations>
              <CountryOfOriginCode>
                <xsl:value-of select="Locations/CountryOfOriginCode"/>
              </CountryOfOriginCode>
              <xsl:for-each select="Locations/ItemCountryonRouteCode">
                <ItemCountryonRouteCode>
                  <xsl:value-of select="."/>
                </ItemCountryonRouteCode>
              </xsl:for-each>
              <ItemDispatchCountry>
                <xsl:value-of select="Locations/ItemDispatchCountry"/>
              </ItemDispatchCountry>
              <ItemDestinationCountry>
                <xsl:value-of select="Locations/ItemDestinationCountry"/>
              </ItemDestinationCountry>
            </Locations>
            <Measurements>
              <GrossMass>
                <xsl:value-of select="Measurements/GrossMass"/>
              </GrossMass>
              <NetMass>
                <xsl:value-of select="Measurements/NetMass"/>
              </NetMass>
              <SupplementaryUnits>
                <xsl:value-of select="Measurements/SupplementaryUnits"/>
              </SupplementaryUnits>
              <ThirdQuantity>
                <xsl:value-of select="Measurements/ThirdQuantity"/>
              </ThirdQuantity>
            </Measurements>
            <xsl:for-each select="Package">
              <Package>
                <PackageNumber>
                  <xsl:value-of select="PackageNumber"/>
                </PackageNumber>
                <PackageKind>
                  <xsl:value-of select="PackageKind"/>
                </PackageKind>
                <PackageMarks>
                  <xsl:value-of select="PackageMarks"/>
                </PackageMarks>
                <PackageLanguage>
                  <xsl:value-of select="PackageLanguage"/>
                </PackageLanguage>
              </Package>
            </xsl:for-each>
            <PriceValue>
              <ItemStatisticalValue>
                <xsl:value-of select="PriceValue/ItemStatisticalValue"/>
              </ItemStatisticalValue>
              <ItemPrice>
                <xsl:value-of select="PriceValue/ItemPrice"/>
              </ItemPrice>
            </PriceValue>
            <ItemReferences>
              <xsl:for-each select="ItemReferences/ContainerID">
                <ContainerID>
                  <xsl:value-of select="."/>
                </ContainerID>
              </xsl:for-each>
              <QuotaNo>
                <xsl:value-of select="ItemReferences/QuotaNo"/>
              </QuotaNo>
              <UNDangerousGoodsCode>
                <xsl:value-of select="ItemReferences/UNDangerousGoodsCode"/>
              </UNDangerousGoodsCode>
            </ItemReferences>
            <GoodsDescription>
              <GoodsDescription>
                <xsl:value-of select="GoodsDescription/GoodsDescription"/>
              </GoodsDescription>
              <GoodsDescriptionLanguage>
                <xsl:value-of select="GoodsDescription/GoodsDescriptionLanguage"/>
              </GoodsDescriptionLanguage>
            </GoodsDescription>
            <Documents>
              <xsl:for-each select="Documents/PreviousDocument">
                <PreviousDocument>
                  <PreviousDocumentKind>
                    <xsl:value-of select="PreviousDocumentKind"/>
                  </PreviousDocumentKind>
                  <PreviousDocumentIdentifier>
                    <xsl:value-of select="PreviousDocumentIdentifier"/>
                  </PreviousDocumentIdentifier>
                  <PreviousDocumentType>
                    <xsl:value-of select="PreviousDocumentType"/>
                  </PreviousDocumentType>
                  <PreviousDocumentLanguage>
                    <xsl:value-of select="PreviousDocumentLanguage"/>
                  </PreviousDocumentLanguage>
                </PreviousDocument>
              </xsl:for-each>
              <xsl:for-each select="Documents/ItemDocument">
                <ItemDocument>
                  <DocumentCode>
                    <xsl:value-of select="DocumentCode"/>
                  </DocumentCode>
                  <DocumentPart>
                    <xsl:value-of select="DocumentPart"/>
                  </DocumentPart>
                  <DocumentQuantity>
                    <xsl:value-of select="DocumentQuantity"/>
                  </DocumentQuantity>
                  <DocumentReason>
                    <xsl:value-of select="DocumentReason"/>
                  </DocumentReason>
                  <DocumentReference>
                    <xsl:value-of select="DocumentReference"/>
                  </DocumentReference>
                  <DocumentStatus>
                    <xsl:value-of select="DocumentStatus"/>
                  </DocumentStatus>
                  <DocumentLanguage>
                    <xsl:value-of select="DocumentLanguage"/>
                  </DocumentLanguage>
                </ItemDocument>
              </xsl:for-each>
            </Documents>
            <Valuation>
              <ValuationMethodCode>
                <xsl:value-of select="Valuation/ValuationMethodCode"/>
              </ValuationMethodCode>
              <ItemValuationAdjustmentCode>
                <xsl:value-of select="Valuation/ItemValuationAdjustmentCode"/>
              </ItemValuationAdjustmentCode>
              <ItemValuationAdjustmentPercentage>
                <xsl:value-of select="Valuation/ItemValuationAdjustmentPercentage"/>
              </ItemValuationAdjustmentPercentage>
            </Valuation>
            <ItemTransportChargeMOP>
              <xsl:value-of select="ItemTransportChargeMOP"/>
            </ItemTransportChargeMOP>
            <xsl:for-each select="ItemProcessingInstructions">
              <ItemProcessingInstructions>
                <xsl:value-of select="."/>
              </ItemProcessingInstructions>
            </xsl:for-each>
          </Items>
        </xsl:for-each>
        <NumberOfPackages>
          <xsl:value-of select="/Declaration/Header/NumberOfPackages"/>
        </NumberOfPackages>
      </Header>
    </Declaration>
  </xsl:template>
</xsl:stylesheet>

所以 for source xml

<Declaration>
    <Message>
        <Meduim>#+#</Meduim>
        <MessageIdentifier>AA</MessageIdentifier>
        <CommonAccessReference></CommonAccessReference>
    </Message>
    <BeginingOfMessage>
        <MessageCode>ISD</MessageCode>
        <DeclarationCurrency></DeclarationCurrency>
        <MessageFunction>5</MessageFunction>
    </BeginingOfMessage>
</Declaration>

最终输出

<Declaration>
    <Message>
        <Meduim></Meduim>
        <MessageIdentifier>AA</MessageIdentifier>
    </Message>
    <BeginingOfMessage>
        <MessageCode>ISD</MessageCode>
        <MessageFunction>5</MessageFunction>
    </BeginingOfMessage>
</Declaration>

3 个答案:

答案 0 :(得分:2)

<强>予。在XSLT应用程序中经常使用转换链,但在XSLT 1.0中完全执行此操作需要使用特定于供应商的xxx:node-set()函数。在XSLT 2.0中,不需要这样的扩展,因为那里消除了臭名昭着的RTF数据类型。

以下是一个示例(过于简单而无意义,但完全说明了如何完成此操作):

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

 <xsl:template match="/">
   <xsl:variable name="vrtfPass1">
    <xsl:apply-templates select="/*/*"/>
   </xsl:variable>

   <xsl:variable name="vPass1"
        select="ext:node-set($vrtfPass1)"/>

   <xsl:apply-templates mode="pass2"
        select="$vPass1/*"/>
 </xsl:template>

 <xsl:template match="num[. mod 2 = 1]">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="num" mode="pass2">
  <xsl:copy>
    <xsl:value-of select=". *2"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

产生了想要的正确结果

<num>2</num>
<num>6</num>
<num>10</num>
<num>14</num>
<num>18</num>

<强>解释

  1. 在第一步中,XML文档被转换,结果被定义为变量$vrtfPass1的值。这仅复制具有奇数值(不均匀)的num元素。

  2. $vrtfPass1变量(RTF类型)不能直接用于XPath表达式,因此我们使用EXSLT将其转换为普通树(由大多数XSLT实现) 1.0处理器)函数ext:node-set并定义另一个变量 - $vPass1,其值为此树。

  3. 我们现在在我们的转换链中执行第二次转换 - 在第一次转换的结果上,保持为变量$vPass1的值。不要混淆第一遍模板,我们指定新处理应该处于命名模式,称为“pass2”。在此模式下,任何num元素的值乘以2。

  4. 另请参阅Michael Kay对您的第一个问题的回答,该问题也解释了这种一般技巧。

    <强> II。 XSLT 2.0解决方案(无RTF):

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/">
      <xsl:variable name="vPass1" >
       <xsl:apply-templates select="/*/*"/>
      </xsl:variable>
       <xsl:apply-templates mode="pass2"
            select="$vPass1/*"/>
     </xsl:template>
    
     <xsl:template match="num[. mod 2 = 1]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match="num" mode="pass2">
      <xsl:copy>
        <xsl:value-of select=". *2"/>
      </xsl:copy>
     </xsl:template>
    </xsl:stylesheet>
    

    <强> III。使用FXSL的compose()compose-flist()函数/模板

    FXSL 库提供了两个方便的函数/模板,支持轻松链接转换。前者组成两个函数/转换,而后者组成序列中提供的所有函数/转换。

    这是一个简单,完整的代码示例

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:f="http://fxsl.sf.net/"
    xmlns:myFun1="f:myFun1"
    xmlns:myFun2="f:myFun2" 
    xmlns:ext="http://exslt.org/common"
    exclude-result-prefixes="xsl f ext myFun1 myFun2"
    >
      <xsl:import href="compose.xsl"/>
      <xsl:import href="compose-flist.xsl"/>
    
      <!-- to be applied on any xml source -->
    
      <xsl:output method="text"/>
      <myFun1:myFun1/>
      <myFun2:myFun2/>
    
    
      <xsl:template match="/">
    
        <xsl:variable name="vFun1" select="document('')/*/myFun1:*[1]"/>
        <xsl:variable name="vFun2" select="document('')/*/myFun2:*[1]"/>
        Compose:
        (*3).(*2) 3 = 
        <xsl:call-template name="compose">
          <xsl:with-param name="pFun1" select="$vFun1"/>
          <xsl:with-param name="pFun2" select="$vFun2"/>
          <xsl:with-param name="pArg1" select="3"/>
        </xsl:call-template>
    
        <xsl:variable name="vrtfParam">
          <xsl:copy-of select="$vFun1"/>
          <xsl:copy-of select="$vFun2"/>
          <xsl:copy-of select="$vFun1"/>
        </xsl:variable>
    
        Multi Compose:
        (*3).(*2).(*3) 2 = 
        <xsl:call-template name="compose-flist">
          <xsl:with-param name="pFunList" select="ext:node-set($vrtfParam)/*"/>
          <xsl:with-param name="pArg1" select="2"/>
        </xsl:call-template>
      </xsl:template>
    
      <xsl:template match="myFun1:*" mode="f:FXSL">
        <xsl:param name="pArg1"/>
    
        <xsl:value-of select="3 * $pArg1"/>
      </xsl:template>
    
      <xsl:template match="myFun2:*" mode="f:FXSL">
        <xsl:param name="pArg1"/>
    
        <xsl:value-of select="2 * $pArg1"/>
      </xsl:template>
    </xsl:stylesheet>
    

    当对任何XML文档(未使用)应用此转换时,会生成所需的正确结果

    Compose:
    (*3).(*2) 3 = 
    18
    
    Multi Compose:
    (*3).(*2).(*3) 2 = 
    36
    

答案 1 :(得分:0)

Pure XSLT 1.0不支持链接模板(也不支持样式表)。你可以通过调用第二个xslt模板并在第一个手动传递第一个xslt模板的输出来解决XSLT之外的这个程序,或者你可以使用相当普遍的扩展函数node-set()。 MSXML,.NET,EXSL和许多其他实现都支持这样的功能。 node-set的名称空间前缀因XSLT实现而异,但EXSL前缀是一个不错的选择(而.NET,虽然没有文档,但支持这一点)。

使用node-set将模板的结果存储在xsl:variablexsl:param中,并执行<xsl:apply-templates select="exsl:node-set($myvarname)"/>之类的操作。

最后,您当然可以重写两个模板,以便在一次传递中提供两者的功能 - 但在一般中,这不是一件容易的事。

答案 2 :(得分:0)

我不明白这个问题。 我在上一个问题中发布的解决方案已经有效。

对于此输入:

<?xml version="1.0" encoding="UTF-8"?>
<Declaration>
    <Message>
        <Meduim>#+#</Meduim>
        <MessageIdentifier>AA</MessageIdentifier>
        <CommonAccessReference></CommonAccessReference>
    </Message>
    <BeginingOfMessage>
        <MessageCode>ISD</MessageCode>
        <DeclarationCurrency></DeclarationCurrency>
        <MessageFunction>5</MessageFunction>
    </BeginingOfMessage>
</Declaration>

输出将是:

<?xml version="1.0" encoding="UTF-8"?>
<Declaration>
    <Message>
        <Meduim/>
        <MessageIdentifier>AA</MessageIdentifier>
    </Message>
    <BeginingOfMessage>
        <MessageCode>ISD</MessageCode>
        <MessageFunction>5</MessageFunction>
    </BeginingOfMessage>
</Declaration>

事实上,您不需要原始样式表,因为基本上您只需复制树。

相关问题