Объединить функциональность двух файлов xsl в один файл (продолжение .....) - PullRequest
1 голос
/ 10 января 2011

Это продолжение моего вопроса:

Объединение функциональных возможностей двух файлов 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>

Ответы [ 3 ]

2 голосов
/ 10 января 2011

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, значением которой является это дерево.*

    Теперь мы выполняем второе преобразование в нашей цепочке преобразований - по результату первого преобразования, которое сохраняется как значение переменной $vPass1.Чтобы не связываться с шаблоном первого прохода, мы указываем, что новая обработка должна быть в именованном режиме, называемом «pass2».В этом режиме значение любого элемента num умножается на два.

См. Также ответ Майкла Кея на ваш первый вопрос, который также объяснил эту общую технику.

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.Использование compose() и compose-flist() функций / шаблонов FXSL

Библиотека 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
0 голосов
/ 10 января 2011

Я не понимаю проблемы. Решение, которое я разместил в вашем последнем вопросе, уже работает.

Для этого ввода:

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

На самом деле вам не нужна исходная таблица стилей, потому что вы просто копируете дерево.

0 голосов
/ 10 января 2011

Pure XSLT 1.0 не поддерживает шаблоны цепочек (ни таблицы стилей в целом).Вы можете решить эту программу вне XSLT, вызвав второй шаблон xslt и передав ему выходные данные первого вручную, или вы можете использовать довольно распространенную функцию расширения node-set().MSXML, .NET, EXSL и многие другие реализации поддерживают такую ​​функцию.Префикс пространства имен для node-set варьируется в зависимости от реализации XSLT, но префикс EXSL - хорошая ставка (и .NET, хотя и недокументированный, поддерживает это).

Для использования node-set сохраните результат шаблонав xsl:variable или xsl:param и выполните что-то вроде <xsl:apply-templates select="exsl:node-set($myvarname)"/>.

Наконец, вы, конечно, можете переписать два ваших шаблона, чтобы обеспечить функциональность обоих за один проход - но в general , это не тривиальная вещь.

...