2014-09-05 66 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