1

这是我的问题的延续:

将两个 xsl 文件的功能合并到一个文件中(不是 xsl 导入或包含问题)


我必须将上述问题的解决方案(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>

所以对于源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>
4

3 回答 3

2

I. 在 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。

另请参阅 Michael Kay 对您的第一个问题的回答,其中也解释了这种通用技术。

二、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>

三、使用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
于 2011-01-10T14:01:53.977 回答
0

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

要使用node-set将模板的结果存储在xsl:variableor中xsl:param并执行类似<xsl:apply-templates select="exsl:node-set($myvarname)"/>.

最后,您当然可以重写您的两个模板以一次性提供两者的功能 - 但总的来说,这不是一件容易的事。

于 2011-01-10T12:45:21.030 回答
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>

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

于 2011-01-10T12:57:37.683 回答