我们每天都有一个外部提供商发送的xml文件,如下所示:
<StreamStart>
<Stream>
... data nodes
</Stream>
</StreamStart>
<DDIVouchers>
<Voucher>
... data nodes
</Voucher>
</DDIVouchers>
<StreamEnd>
<Stream>
... data nodes
</Stream>
</StreamEnd>
我的xslt工作正常,这是:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msg="http://www.voca.com/schemas/messaging"
xmlns:cmn="http://www.voca.com/schemas/common"
xmlns:str="http://exslt.org/strings" extension-element-prefixes="str" >
<xsl:output method="text" encoding="UTF-8" />
<xsl:strip-space elements="AccountName TransactionCode" />
<!--
defined template to convert YYYY-MM-DD into CYYMMDD
so 2014-08-14 becomes 1140814 which is good for Equation
-->
<xsl:template name="date">
<xsl:param name="yyyy-mm-dd"/>
<xsl:variable name="yyyy" select="substring-before($yyyy-mm-dd, '-')"/> <!-- extract the year-->
<xsl:variable name="mm-dd" select="substring-after($yyyy-mm-dd, '-')"/> <!-- extract the month and day-->
<xsl:variable name="mm" select="substring-before($mm-dd, '-')"/> <!-- extract the month-->
<xsl:variable name="dd" select="substring-after($mm-dd, '-')"/> <!-- extract the day-->
<!-- now determine if it will be 0 for before 2000, or 1 for after-->
<xsl:choose>
<xsl:when test="substring($yyyy,1,2)='19'">0</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="substring($yyyy,3,4)"/>
<xsl:value-of select="$mm"/>
<xsl:value-of select="$dd"/>
</xsl:template>
<!--
named template to first remove all the leading and trailing spaces,
then output the result with a total fixed length of 71 characters
-->
<xsl:template name="FormattedPhoneFaxNumber">
<xsl:param name="text"/>
<xsl:variable name="noSpaces" select="normalize-space($text)" />
<xsl:value-of select="substring(concat(' ', $noSpaces), string-length($noSpaces) + 1)"/>
</xsl:template>
<xsl:template match="/">
<!--
Explanation:
The instruction:
<xsl:for-each select="msg:VocaDocument/msg:Data/msg:Document/msg:DDIVouchers/msg:Voucher">
puts us in the context of Voucher (within the default name-space that has been aliased to 'msg'. In this context, the path:
"../../StreamStart/Stream/BankName"
goes "up" to the parent element twice (i.e. to Document) and from there "down" to StreamStart/Stream/BankName where the required value is.
string-length(../../msg:StreamEnd/msg:Stream/msg:StreamCode)
-->
<!-- START LOOP THROUGH ALL VOUCHERS-->
<xsl:for-each select="msg:VocaDocument/msg:Data/msg:Document/msg:DDIVouchers/msg:Voucher">
<!-- STREAM START-->
<xsl:value-of select="substring(concat(../../msg:StreamStart/msg:Stream/msg:BankName, ' '), 1, 70)"/>
<xsl:value-of select="substring(concat(../../msg:StreamStart/msg:Stream/msg:BankCode, '0000'), 1, 4)"/>
<xsl:value-of select="substring(concat('0000', ../../msg:StreamStart/msg:Stream/msg:StreamCode), 3 ,4)"/>
<xsl:value-of select="../../msg:StreamStart/msg:Stream/msg:VoucherSortCode"/>
<xsl:value-of select="substring(concat(../../msg:StreamStart/msg:Stream/msg:VoucherAccountNumber, '00000000'), 1, 8)"/>
<xsl:value-of select="substring(concat(../../msg:StreamStart/msg:Stream/msg:TotalVouchers, '00000000'), 1, 8)"/>
<!-- VOUCHER START-->
<xsl:value-of select="substring(concat(translate((msg:TransactionCode), ' ',''), ' '), 1, 10)"/>
<xsl:value-of select="substring(concat(msg:OriginatorIdentification/msg:ServiceUserName, ' '), 1, 35)"/>
<xsl:value-of select="substring(concat(msg:OriginatorIdentification/msg:ServiceUserNumber, ' '), 1, 6)"/>
<xsl:value-of select="substring(concat(msg:PayingBankAccount/msg:BankName, ' '), 1, 70)"/>
<xsl:value-of select="substring(concat(normalize-space(msg:PayingBankAccount/msg:AccountName), ' '), 1, 18)"/>
<xsl:value-of select="substring(concat(normalize-space(msg:PayingBankAccount/msg:AccountNumber), ' '), 1, 8)"/>
<xsl:value-of select="substring(concat(normalize-space(msg:PayingBankAccount/msg:UkSortCode), ' '), 1, 8)"/>
<xsl:value-of select="substring(concat(normalize-space(msg:ReferenceNumber), ' '), 1, 18)"/>
<xsl:call-template name="FormattedPhoneFaxNumber">
<xsl:with-param name="text" select="msg:ContactDetails/msg:PhoneNumber" />
</xsl:call-template>
<xsl:call-template name="FormattedPhoneFaxNumber">
<xsl:with-param name="text" select="msg:ContactDetails/msg:FaxNumber" />
</xsl:call-template>
<!-- NOTE HOW TO EXTRACT AN ADDRESS ELEMENT THAT HAS ITS OWN NAMESPACE -->
<xsl:value-of select="substring(concat(msg:ContactDetails/msg:Address/cmn:AddresseeName, ' '), 1, 33)"/>
<xsl:value-of select="substring(concat(msg:ContactDetails/msg:Address/cmn:PostalName, ' '), 1, 33)"/>
<xsl:value-of select="substring(concat(msg:ContactDetails/msg:Address/cmn:AddressLine, ' '), 1, 33)"/>
<xsl:value-of select="substring(concat(msg:ContactDetails/msg:Address/cmn:TownName, ' '), 1, 30)"/>
<xsl:value-of select="substring(concat(msg:ContactDetails/msg:Address/cmn:CountyIdentification, ' '), 1, 40)"/>
<xsl:value-of select="substring(concat(msg:ContactDetails/msg:Address/cmn:CountryName, ' '), 1, 40)"/>
<xsl:value-of select="substring(concat(msg:ContactDetails/msg:Address/cmn:ZipCode, ' '), 1, 10)"/>
<xsl:call-template name="date">
<xsl:with-param name="yyyy-mm-dd" select="msg:ProcessingDate"/>
</xsl:call-template>
<xsl:value-of select="substring(concat(msg:BankAccount/msg:FirstLastVoucherCode, ' '), 1, 15)"/>
<xsl:value-of select="substring(concat(msg:BankAccount/msg:AgencyBankCode, '0000'), 1, 4)"/>
<xsl:value-of select="substring(concat(msg:BankAccount/msg:SortCode, '00000000'), 1, 8)"/>
<xsl:value-of select="substring(concat(msg:BankAccount/msg:AccountNumber, '00000000'), 1, 8)"/>
<xsl:value-of select="substring(concat('000000000000000', msg:BankAccount/msg:Counter), string-length(msg:BankAccount/msg:Counter) + 1, 15)"/>
<!-- STREAM END-->
<xsl:value-of select="substring(concat(../../msg:StreamEnd/msg:Stream/msg:BankName, ' '), 1, 70)"/>
<xsl:value-of select="substring(concat(../../msg:StreamEnd/msg:Stream/msg:BankCode, '0000'), 1, 4)"/>
<xsl:value-of select="substring(concat('0000', ../../msg:StreamEnd/msg:Stream/msg:StreamCode), 3 ,4)"/>
<xsl:value-of select="substring(concat(../../msg:StreamEnd/msg:Stream/msg:VoucherSortCode, '00000000'), 1, 8)"/>
<xsl:value-of select="substring(concat(../../msg:StreamEnd/msg:Stream/msg:VoucherAccountNumber, '00000000'), 1, 8)"/>
<xsl:value-of select="substring(concat('00000000', ../../msg:StreamEnd/msg:Stream/msg:TotalVouchers), string-length(../../msg:StreamEnd/msg:Stream/msg:TotalVouchers) + 1, 8)"/>
<!-- CR/LF NEW LINE 
-->
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这是显示结尾处空行的输出:
在输出输出中,我们最后得到2个空行....对我来说似乎没有理由。
我可以在我的XSLT样式表中添加或更改某些内容,以防止在输出结尾处出现这些额外的空白行(这是一个固定宽度的文本文件,将被加载到另一个会计系统中。
修改
我还尝试在样式表的最后添加这两个模板:
<xsl:template match="text()[not(string-length(normalize-space()))]"/>
<xsl:template match="text()[string-length(normalize-space()) > 0]">
<xsl:value-of select="translate(.,'

', ' ')"/>
</xsl:template>
(来自SO:5737862 (answer by Dimitre),但我没有运气,或者其他可能是错误的。
编辑2: 额外的行是否可能是MS XMSL 6 DOM Document TransformNode 方法的结果,我在Excel VBA中使用它来生成测试文件输出?
答案 0 :(得分:2)
您无条件地添加换行符 :
<!-- CR/LF NEW LINE 
--> <xsl:text>
</xsl:text>
请尝试此操作(另请注意,换行符实际为

):
<xsl:if test="position () < last()">
<xsl:text>
</xsl:text>
</xsl:if>