这是我的问题的继续:
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>
答案 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>
<强>解释强>:
在第一步中,XML文档被转换,结果被定义为变量$vrtfPass1
的值。这仅复制具有奇数值(不均匀)的num
元素。
$vrtfPass1
变量(RTF类型)不能直接用于XPath表达式,因此我们使用EXSLT将其转换为普通树(由大多数XSLT实现) 1.0处理器)函数ext:node-set
并定义另一个变量 - $vPass1
,其值为此树。
我们现在在我们的转换链中执行第二次转换 - 在第一次转换的结果上,保持为变量$vPass1
的值。不要混淆第一遍模板,我们指定新处理应该处于命名模式,称为“pass2”。在此模式下,任何num
元素的值乘以2。
另请参阅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:variable
或xsl: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>
事实上,您不需要原始样式表,因为基本上您只需复制树。