2014-09-05 64 views
2

我们必须由外部供应商每天发送的xml文件,看起来像这样:防止XSLT在文件末尾的空白输出线1.0

<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 &#xA;--> 
     <xsl:text>&#xD;</xsl:text> 

    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

这里是表示在端部的空行的输出:

enter image description here

在输出中,我们在最后得到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(.,'&#xA;&#xD;', ' ')"/> 
</xsl:template> 

(从SO:5737862 (answer by Dimitre)但我没有运气,或者是someth否则是错误的。

编辑2: 是否有可能的是,额外的行是MS XMSL 6 DOM文档的transformNode方法中,我使用在Excel VBA其中以生成测试文件输出的结果?

+1

两个问题:如果你会发生什么使用' '而不是' '换行符?而且,如果你使用''换行符? – Tomalak 2014-09-05 15:28:06

+0

与' '这是一样的。使用''它会失败并显示'XML错误' – 2014-09-05 15:39:28

+1

您确实关闭了,不是吗? – Tomalak 2014-09-05 15:41:06

回答

2

您可以附加一个换行符无条件

<!-- CR/LF NEW LINE &#xA;--> 
<xsl:text>&#xD;</xsl:text> 

试试这个(还注意到,换行实际上是&#xA;):

<xsl:if test="position() &lt; last()"> 
    <xsl:text>&#xA;</xsl:text> 
</xsl:if> 
+1

谢谢,这解决了它 - 它看起来像它可能是MSXML在'transformNode'方法上做的。 – 2014-09-05 16:18:56