1

I am using the Saxon XsltTransformer to transform the XML of electronic invoices ("XRechnungen", the German adaption). The invoices are XML files with "un/cefact CII" or "UBL" syntax and both need to be translated in the same XR syntax.

For UBL I use the files "ubl_invoice_xr.xsl" and "ubl_creditnore_xr.xsl" and this works without any problems.

For CII I use the "cii_xr.xsl" from https://github.com/itplr-kosit/xrechnung-visualization/tree/master/src/xsl but the result omits the allowances and charges (both on invoice_line-level and document-level).

At https://github.com/itplr-kosit/xrechnung-testsuite/tree/master/src/test/business-cases/standard I found a lot of test invoices ("uncefact" suffix) bot none of them is transformed correctly.

Looking at the "cii-xr.xsl" you find:

<xsl:template mode="BG-20"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false']">

      <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false'] der Instanz in konkreter Syntax wird auf 7 Objekte der EN 16931 abgebildet. -->
         <xsl:apply-templates mode="BT-92" select="./ram:ActualAmount"/>
         <xsl:apply-templates mode="BT-93" select="./ram:BasisAmount"/>
         <xsl:apply-templates mode="BT-94" select="./ram:CalculationPercent"/>
         <xsl:apply-templates mode="BT-95" select="./ram:CategoryTradeTax/ram:CategoryCode"/>
         <xsl:apply-templates mode="BT-96" select="./ram:CategoryTradeTax/ram:RateApplicablePercent"/>
         <xsl:apply-templates mode="BT-97" select="./ram:Reason"/>
         <xsl:apply-templates mode="BT-98" select="./ram:ReasonCode"/>
      </xsl:variable>
      <xsl:if test="$bg-contents">
         <xr:DOCUMENT_LEVEL_ALLOWANCES>
            <xsl:attribute name="xr:id" select="'BG-20'"/>
            <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
            <xsl:sequence select="$bg-contents"/>
         </xr:DOCUMENT_LEVEL_ALLOWANCES>
      </xsl:if>
   </xsl:template>
   <xsl:template mode="BT-92"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount">
      <xr:Document_level_allowance_amount>
         <xsl:attribute name="xr:id" select="'BT-92'"/>
         <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
         <xsl:call-template name="amount"/>
      </xr:Document_level_allowance_amount>
   </xsl:template>
   <xsl:template mode="BT-93"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount">
      <xr:Document_level_allowance_base_amount>
         <xsl:attribute name="xr:id" select="'BT-93'"/>
         <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
         <xsl:call-template name="amount"/>
      </xr:Document_level_allowance_base_amount>
   </xsl:template>
   <xsl:template mode="BT-94"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent">
      <xr:Document_level_allowance_percentage>
         <xsl:attribute name="xr:id" select="'BT-94'"/>
         <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
         <xsl:call-template name="percentage"/>
      </xr:Document_level_allowance_percentage>
   </xsl:template>
   <xsl:template mode="BT-95"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode">
      <xr:Document_level_allowance_VAT_category_code>
         <xsl:attribute name="xr:id" select="'BT-95'"/>
         <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
         <xsl:call-template name="code"/>
      </xr:Document_level_allowance_VAT_category_code>
   </xsl:template>
   <xsl:template mode="BT-96"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:RateApplicablePercent">
      <xr:Document_level_allowance_VAT_rate>
         <xsl:attribute name="xr:id" select="'BT-96'"/>
         <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
         <xsl:call-template name="percentage"/>
      </xr:Document_level_allowance_VAT_rate>
   </xsl:template>
   <xsl:template mode="BT-97"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:Reason">
      <xr:Document_level_allowance_reason>
         <xsl:attribute name="xr:id" select="'BT-97'"/>
         <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
         <xsl:call-template name="text"/>
      </xr:Document_level_allowance_reason>
   </xsl:template>
   <xsl:template mode="BT-98"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode">
      <xr:Document_level_allowance_reason_code>
         <xsl:attribute name="xr:id" select="'BT-98'"/>
         <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
         <xsl:call-template name="code"/>
      </xr:Document_level_allowance_reason_code>
   </xsl:template>

So the output file should contain "<xr:DOCUMENT_LEVEL_ALLOWANCES>" tags with (for example) "</xr:Document_level_allowance_amount>" children, but it does not. No matter if the input file has allowances/charges in the "invoice_lines" or at "document_level".

Since I use vb.NET I use the .NET wrapper of saxon-HE:

 Public Shared Function Cii2UnifiedXML(ByVal vsXmlFilePath As String) As Result
            Dim cproc As New Saxon.Api.Processor
            Dim cComp As Saxon.Api.XsltCompiler = cproc.NewXsltCompiler
            Dim exe As Saxon.Api.XsltExecutable            
            Dim inputStream As New StreamReader(vsXmlFilePath)
#Disable Warning BC40000 ' I know, XmlDataDocument is deprecated
            Dim xmldoc As New XmlDataDocument()
#Enable Warning BC40000
            Dim cResult As New Result
            Dim ctrans As Saxon.Api.XsltTransformer
            Dim seri As Saxon.Api.Serializer
            Dim sPath As String = String.Empty
            Dim sFilename As String = String.Empty
            Dim outStream As FileStream = Nothing

            Try
                exe = cComp.Compile(New MemoryStream(Encoding.UTF8.GetBytes(My.Resources.cii_xr)))
                ctrans = exe.Load
                seri = cproc.NewSerializer
                sPath = Path.GetDirectoryName(vsXmlFilePath)
                sFilename = Path.Combine(sPath, $"{Path.GetFileNameWithoutExtension(vsXmlFilePath)}_Unified.xml")
                outStream = New FileStream(sFilename, FileMode.Create, FileAccess.Write)

                ctrans.SetInputStream(inputStream.BaseStream, New Uri(sPath))
                seri.SetOutputStream(outStream)
                ctrans.Run(seri)

                cResult.Success = True
                cResult.Obj = sFilename
            Catch ex As Exception
                cResult.Exception = ex
                cResult.Success = False
                cResult.ErrorMsg = ex.Message
            Finally
                xmldoc = Nothing
                If outStream IsNot Nothing Then outStream.Close()
                If inputStream IsNot Nothing Then inputStream.Close()
            End Try

            Return cResult
        End Function

I don't know if I don't understand how the XsltCompiler works (and therefore I am too stupid) or if it's a bug, since the translation of UBL invoices works great. The output file of UBL translations contains the elements "DOCUMENT_LEVEL_ALLOWANCES", "DOCUMENT_LEVEL_CHARGES", "INVOICE_LINE_ALLOWANCES" and "INVOICE_LINE_CHARGES".

All files can be found at https://github.com/itplr-kosit

Thanks a lot

  • Have you used another XSLT processor that gives the "right" result? Have you asked the maintainers of the stylesheet which XSLT processor it is supposed to be run with? If you are in doubt of your VB.NET code then perhaps first run Saxon from the command line to test whether the stylesheets do what you expect them to do. – Martin Honnen Nov 24 '20 at 11:12
  • Hi Martin, yes I tried another offline tool and also https://xslttest.appspot.com My invoices (real and test) do not get translated properly. See my answer to Michael Kay's comment. I got a whole bunch of invoices of different companies with allowances and charges but every single output file omits them. – Markus Schnepf Nov 26 '20 at 08:35
  • Do you think that it is a Saxon issue? Or are the used stylesheets just not up to the job with that particular input you have? Do the KoSit people have any recommendations? – Martin Honnen Nov 26 '20 at 08:39
  • I asked but KoSit told me that they don't have a development support team. The only do the definitions. I should ask the developers. Since there is no customer support for the "Saxon HE" (open source) version they recommend to ask on stackoverflow with the tag "saxon", which I used. I already tried it with multiple (online) transormation tools and the result always ommits the charges. So yes, I think the definition file "cii-xr.xsl" is faulty. But it contains a definition for "SpecifiedTradeAllowanceCharge" (see comments by Michael Kay) – Markus Schnepf Dec 01 '20 at 10:13

3 Answers3

1

It's hard to make much headway on debugging this for you because I don't understand the XML vocabulary or the logic of the stylesheet. However, I tried it on one sample document from the test set, and the template rule you show us with

    <xsl:template mode="BG-20" match="/rsm:CrossIndustryInvoice
        /rsm:SupplyChainTradeTransaction
        /ram:ApplicableHeaderTradeSettlement
        /ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false']">

doesn't get executed because the ApplicableHeaderTradeSettlement element in the source document doesn't have a child called SpecifiedTradeAllowanceCharge.

Of course I've no idea what this means or how you fix it, but there's no evidence that the stylesheet isn't doing what it was designed to do on the one source document that I tested.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Hi Michael, thanks a lot for your answer. Yeah I noticed that there are different test cases on/in these invoices. But I have an invoice with a "SpecifiedTradeAllowanceCharge" within a "ApplicableHeaderTradeSettlement ". Unfortunatelly I cannot send the whole invoice since it's a real invoice from a real company. [link](https://pasteboard.co/JC7vgof.png) – Markus Schnepf Nov 26 '20 at 08:32
  • If you can't provide a test case that demonstrates the failure, then we can't tell you why it's failing. – Michael Kay Nov 26 '20 at 08:57
  • Hi Michael, I replaced the sensitive information with *DummyValues* and uploaded the XML to pastebin: https://pastebin.com/JS0CFsSM Thats one of many real invoices I got and there is a "SpecifiedTradeAllowanceCharge" withing a "ApplicableHeaderTradeSettlement". – Markus Schnepf Dec 01 '20 at 10:10
0

The match is /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false'] looking for the value false in the predicate while your input sample seems to have the value true. So that could be one reason why the templates you have cited are not applied.

Another reason could be the wrong predicate or the lack of <xsl:strip-space/> although the online XSLT seems to use the right predicate [ram:ChargeIndicator/udt:Indicator='false'], i.e. with the additional child.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
0

the problem was found, you won't believe what caused it... we tried several XR-visualizer that showed the charges and allowances correctly. We tried several translation tools (web + desktop) but none of them created the output file correctly (with allowances and charges). Most validator tools for "XPath" showed the invoices as "correct" but only ONE told us, that there is a line break between the "indicator" element and it's parent element "ChargeIndicator".

Of course... there are hundreds of line breaks everywhere?

This block in the cii invoice file does NOT work:

<ram:ChargeIndicator>
    <udt:Indicator>true</udt:Indicator>
</ram:ChargeIndicator>          

but this works:

<ram:ChargeIndicator><udt:Indicator>true</udt:Indicator></ram:ChargeIndicator>

I tried to contact the kosit several times but they have no telephone hotline for development issues and I did not get a reply to the mails I wrote 8, 5 and 2 weeks ago.

That's funny, because the version XRechnung 2.0 will be mandatory to use by 1st jan. 2021.

Thanks for all your ideas guys