Skip to content

Commit 023c616

Browse files
authored
Fix: Handle BOM in xml before parsing with XslTransformer (#11)
* Add testcase with BOM in XML prolog for converting to html * Add new helper class to remove BOM from Xml-String * Change handlers to normalize said string
1 parent 77f594f commit 023c616

File tree

5 files changed

+198
-2
lines changed

5 files changed

+198
-2
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.github.easybill.xrviz;
2+
3+
public class XmlHelper {
4+
public static String removeBOM(String str) {
5+
// Check if XML contains BOM, if so, we will remove if due to the XslTransformer having issues with anything
6+
// before the XML prolog.
7+
if (str.startsWith("\uFEFF")) {
8+
return str.substring(1);
9+
}
10+
11+
return str;
12+
}
13+
14+
}

src/main/java/io/github/easybill/xrviz/handler/HtmlHandler.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.sun.net.httpserver.HttpExchange;
44
import com.sun.net.httpserver.HttpHandler;
5+
import io.github.easybill.xrviz.XmlHelper;
56
import io.github.easybill.xrviz.XslTransformer;
67

78
import javax.xml.transform.TransformerException;
@@ -14,11 +15,14 @@ public void handle(HttpExchange exchange) throws IOException {
1415
logger.info("HTML conversion requested");
1516
try {
1617
var xml = validate(exchange);
18+
1719
if (xml.isEmpty()) {
1820
return;
1921
}
2022

21-
byte[] response = XslTransformer.transformToHtml(xml.get(), getLanguage(exchange)).getBytes(StandardCharsets.UTF_8);
23+
var xmlContent = XmlHelper.removeBOM(xml.get());
24+
25+
byte[] response = XslTransformer.transformToHtml(xmlContent, getLanguage(exchange)).getBytes(StandardCharsets.UTF_8);
2226

2327
exchange.getResponseHeaders().set("Content-Type", "text/html");
2428
exchange.sendResponseHeaders(200, response.length);

src/main/java/io/github/easybill/xrviz/handler/PdfHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import com.sun.net.httpserver.HttpExchange;
44
import com.sun.net.httpserver.HttpHandler;
5+
import io.github.easybill.xrviz.XmlHelper;
56
import io.github.easybill.xrviz.XslTransformer;
67
import org.apache.fop.apps.FOPException;
8+
import org.apache.fop.render.txt.Helper;
79

810
import javax.xml.transform.TransformerException;
911
import java.io.IOException;
@@ -14,11 +16,14 @@ public void handle(HttpExchange exchange) throws IOException {
1416
logger.info("PDF conversion requested");
1517
try {
1618
var xml = validate(exchange);
19+
1720
if (xml.isEmpty()) {
1821
return;
1922
}
2023

21-
byte[] response = XslTransformer.transformToPdf(xml.get(), getLanguage(exchange));
24+
var xmlContent = XmlHelper.removeBOM(xml.get());
25+
26+
byte[] response = XslTransformer.transformToPdf(xmlContent, getLanguage(exchange));
2227

2328
exchange.getResponseHeaders().set("Content-Type", "application/pdf");
2429
exchange.sendResponseHeaders(200, response.length);

src/test/http/api-test.http

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,18 @@ Content-Type: application/xml
5858
Accept-Language: de
5959

6060
< ./ubl-creditnote.xml
61+
62+
63+
### Generate a PDF file from a XML with UTF-8 BOM
64+
POST {{baseUrl}}/convert.pdf
65+
Content-Type: application/xml
66+
Accept-Language: de
67+
68+
< ./output_with_bom.xml
69+
70+
### Generate a HTML file from a XML with UTF-8 BOM
71+
POST {{baseUrl}}/convert.html
72+
Content-Type: application/xml
73+
Accept-Language: de
74+
75+
< ./output_with_bom.xml

src/test/http/output_with_bom.xml

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?xml version='1.0' encoding='UTF-8' ?>
2+
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
3+
<rsm:ExchangedDocumentContext>
4+
<ram:GuidelineSpecifiedDocumentContextParameter>
5+
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
6+
</ram:GuidelineSpecifiedDocumentContextParameter>
7+
</rsm:ExchangedDocumentContext>
8+
<rsm:ExchangedDocument>
9+
<ram:ID>471102</ram:ID>
10+
<ram:TypeCode>380</ram:TypeCode>
11+
<ram:IssueDateTime>
12+
<udt:DateTimeString format="102">20180305</udt:DateTimeString>
13+
</ram:IssueDateTime>
14+
<ram:IncludedNote>
15+
<ram:Content>Rechnung gemäß Bestellung vom 01.03.2018.</ram:Content>
16+
</ram:IncludedNote>
17+
<ram:IncludedNote>
18+
<ram:Content>Lieferant GmbH
19+
Lieferantenstraße 20
20+
80333 München
21+
Deutschland
22+
Geschäftsführer: Hans Muster
23+
Handelsregisternummer: H A 123
24+
</ram:Content>
25+
<ram:SubjectCode>REG</ram:SubjectCode>
26+
</ram:IncludedNote>
27+
</rsm:ExchangedDocument>
28+
<rsm:SupplyChainTradeTransaction>
29+
<ram:IncludedSupplyChainTradeLineItem>
30+
<ram:AssociatedDocumentLineDocument>
31+
<ram:LineID>1</ram:LineID>
32+
</ram:AssociatedDocumentLineDocument>
33+
<ram:SpecifiedTradeProduct>
34+
<ram:GlobalID schemeID="0160">4012345001235</ram:GlobalID>
35+
<ram:SellerAssignedID>TB100A4</ram:SellerAssignedID>
36+
<ram:Name>Trennblätter A4</ram:Name>
37+
</ram:SpecifiedTradeProduct>
38+
<ram:SpecifiedLineTradeAgreement>
39+
<ram:GrossPriceProductTradePrice>
40+
<ram:ChargeAmount>9.9000</ram:ChargeAmount>
41+
</ram:GrossPriceProductTradePrice>
42+
<ram:NetPriceProductTradePrice>
43+
<ram:ChargeAmount>9.9000</ram:ChargeAmount>
44+
</ram:NetPriceProductTradePrice>
45+
</ram:SpecifiedLineTradeAgreement>
46+
<ram:SpecifiedLineTradeDelivery>
47+
<ram:BilledQuantity unitCode="H87">20.0000</ram:BilledQuantity>
48+
</ram:SpecifiedLineTradeDelivery>
49+
<ram:SpecifiedLineTradeSettlement>
50+
<ram:ApplicableTradeTax>
51+
<ram:TypeCode>VAT</ram:TypeCode>
52+
<ram:CategoryCode>S</ram:CategoryCode>
53+
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
54+
</ram:ApplicableTradeTax>
55+
<ram:SpecifiedTradeSettlementLineMonetarySummation>
56+
<ram:LineTotalAmount>198.00</ram:LineTotalAmount>
57+
</ram:SpecifiedTradeSettlementLineMonetarySummation>
58+
</ram:SpecifiedLineTradeSettlement>
59+
</ram:IncludedSupplyChainTradeLineItem>
60+
<ram:IncludedSupplyChainTradeLineItem>
61+
<ram:AssociatedDocumentLineDocument>
62+
<ram:LineID>2</ram:LineID>
63+
</ram:AssociatedDocumentLineDocument>
64+
<ram:SpecifiedTradeProduct>
65+
<ram:GlobalID schemeID="0160">4000050986428</ram:GlobalID>
66+
<ram:SellerAssignedID>ARNR2</ram:SellerAssignedID>
67+
<ram:Name>Joghurt Banane</ram:Name>
68+
</ram:SpecifiedTradeProduct>
69+
<ram:SpecifiedLineTradeAgreement>
70+
<ram:GrossPriceProductTradePrice>
71+
<ram:ChargeAmount>5.5000</ram:ChargeAmount>
72+
</ram:GrossPriceProductTradePrice>
73+
<ram:NetPriceProductTradePrice>
74+
<ram:ChargeAmount>5.5000</ram:ChargeAmount>
75+
</ram:NetPriceProductTradePrice>
76+
</ram:SpecifiedLineTradeAgreement>
77+
<ram:SpecifiedLineTradeDelivery>
78+
<ram:BilledQuantity unitCode="H87">50.0000</ram:BilledQuantity>
79+
</ram:SpecifiedLineTradeDelivery>
80+
<ram:SpecifiedLineTradeSettlement>
81+
<ram:ApplicableTradeTax>
82+
<ram:TypeCode>VAT</ram:TypeCode>
83+
<ram:CategoryCode>S</ram:CategoryCode>
84+
<ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>
85+
</ram:ApplicableTradeTax>
86+
<ram:SpecifiedTradeSettlementLineMonetarySummation>
87+
<ram:LineTotalAmount>275.00</ram:LineTotalAmount>
88+
</ram:SpecifiedTradeSettlementLineMonetarySummation>
89+
</ram:SpecifiedLineTradeSettlement>
90+
</ram:IncludedSupplyChainTradeLineItem>
91+
<ram:ApplicableHeaderTradeAgreement>
92+
<ram:SellerTradeParty>
93+
<ram:ID>549910</ram:ID>
94+
<ram:GlobalID schemeID="0088">4000001123452</ram:GlobalID>
95+
<ram:Name>Lieferant GmbH</ram:Name>
96+
<ram:PostalTradeAddress>
97+
<ram:PostcodeCode>80333</ram:PostcodeCode>
98+
<ram:LineOne>Lieferantenstraße 20</ram:LineOne>
99+
<ram:CityName>München</ram:CityName>
100+
<ram:CountryID>DE</ram:CountryID>
101+
</ram:PostalTradeAddress>
102+
<ram:SpecifiedTaxRegistration>
103+
<ram:ID schemeID="FC">201/113/40209</ram:ID>
104+
</ram:SpecifiedTaxRegistration>
105+
<ram:SpecifiedTaxRegistration>
106+
<ram:ID schemeID="VA">DE123456789</ram:ID>
107+
</ram:SpecifiedTaxRegistration>
108+
</ram:SellerTradeParty>
109+
<ram:BuyerTradeParty>
110+
<ram:ID>GE2020211</ram:ID>
111+
<ram:Name>Kunden AG Mitte</ram:Name>
112+
<ram:PostalTradeAddress>
113+
<ram:PostcodeCode>69876</ram:PostcodeCode>
114+
<ram:LineOne>Kundenstraße 15</ram:LineOne>
115+
<ram:CityName>Frankfurt</ram:CityName>
116+
<ram:CountryID>DE</ram:CountryID>
117+
</ram:PostalTradeAddress>
118+
</ram:BuyerTradeParty>
119+
</ram:ApplicableHeaderTradeAgreement>
120+
<ram:ApplicableHeaderTradeDelivery>
121+
<ram:ActualDeliverySupplyChainEvent>
122+
<ram:OccurrenceDateTime>
123+
<udt:DateTimeString format="102">20180305</udt:DateTimeString>
124+
</ram:OccurrenceDateTime>
125+
</ram:ActualDeliverySupplyChainEvent>
126+
</ram:ApplicableHeaderTradeDelivery>
127+
<ram:ApplicableHeaderTradeSettlement>
128+
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
129+
<ram:ApplicableTradeTax>
130+
<ram:CalculatedAmount>19.25</ram:CalculatedAmount>
131+
<ram:TypeCode>VAT</ram:TypeCode>
132+
<ram:BasisAmount>275.00</ram:BasisAmount>
133+
<ram:CategoryCode>S</ram:CategoryCode>
134+
<ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>
135+
</ram:ApplicableTradeTax>
136+
<ram:ApplicableTradeTax>
137+
<ram:CalculatedAmount>37.62</ram:CalculatedAmount>
138+
<ram:TypeCode>VAT</ram:TypeCode>
139+
<ram:BasisAmount>198.00</ram:BasisAmount>
140+
<ram:CategoryCode>S</ram:CategoryCode>
141+
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
142+
</ram:ApplicableTradeTax>
143+
<ram:SpecifiedTradePaymentTerms>
144+
<ram:Description>Zahlbar innerhalb 30 Tagen netto bis 04.04.2018, 3% Skonto innerhalb 10 Tagen bis 15.03.2018</ram:Description>
145+
</ram:SpecifiedTradePaymentTerms>
146+
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
147+
<ram:LineTotalAmount>473.00</ram:LineTotalAmount>
148+
<ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
149+
<ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
150+
<ram:TaxBasisTotalAmount>473.00</ram:TaxBasisTotalAmount>
151+
<ram:TaxTotalAmount currencyID="EUR">56.87</ram:TaxTotalAmount>
152+
<ram:GrandTotalAmount>529.87</ram:GrandTotalAmount>
153+
<ram:TotalPrepaidAmount>0.00</ram:TotalPrepaidAmount>
154+
<ram:DuePayableAmount>529.87</ram:DuePayableAmount>
155+
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
156+
</ram:ApplicableHeaderTradeSettlement>
157+
</rsm:SupplyChainTradeTransaction>
158+
</rsm:CrossIndustryInvoice>

0 commit comments

Comments
 (0)