[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs:reading":3},{"versions":4,"version":26,"nav":28,"path":58,"kind":106,"page":107},[5,10,13,16,18,20,22,24],{"name":6,"label":7,"prefix":8,"channel":9},"0.7","0.7 (latest)","","latest",{"name":11,"label":12,"prefix":11,"channel":11},"next","next (unreleased)",{"name":14,"label":14,"prefix":14,"channel":15},"0.6","old",{"name":17,"label":17,"prefix":17,"channel":15},"0.5",{"name":19,"label":19,"prefix":19,"channel":15},"0.4",{"name":21,"label":21,"prefix":21,"channel":15},"0.3",{"name":23,"label":23,"prefix":23,"channel":15},"0.2",{"name":25,"label":25,"prefix":25,"channel":15},"0.1",{"name":6,"label":7,"prefix":8,"channel":9,"base":27},"\u002Fdocs",[29,33,36,39,42,45,48,51,54,57,60,63,66,69,72,75,78,81,84,87,91,94,97,100,103],{"slug":30,"title":31,"preview":32},"index","Home",false,{"slug":34,"title":35,"preview":32},"getting-started","Getting started",{"slug":37,"title":38,"preview":32},"concepts","E-invoicing basics",{"slug":40,"title":41,"preview":32},"examples","Examples",{"slug":43,"title":44,"preview":32},"building-invoices","Building invoices",{"slug":46,"title":47,"preview":32},"formats","Formats and profiles",{"slug":49,"title":50,"preview":32},"validation","Validation",{"slug":52,"title":53,"preview":32},"templates","Templates and design",{"slug":55,"title":56,"preview":32},"documents","Quotes and other documents",{"slug":58,"title":59,"preview":32},"reading","Reading incoming invoices",{"slug":61,"title":62,"preview":32},"laravel","Laravel integration",{"slug":64,"title":65,"preview":32},"configuration","Configuration",{"slug":67,"title":68,"preview":32},"commands","Artisan commands",{"slug":70,"title":71,"preview":32},"testing","Testing",{"slug":73,"title":74,"preview":32},"country-packs","Country packs",{"slug":76,"title":77,"parent":74,"preview":32},"country-at","Austria",{"slug":79,"title":80,"parent":74,"preview":32},"country-be","Belgium",{"slug":82,"title":83,"parent":74,"preview":32},"country-ch","Switzerland",{"slug":85,"title":86,"parent":74,"preview":32},"country-fr","France",{"slug":88,"title":89,"preview":90},"managed","Managed layer (preview)",true,{"slug":92,"title":93,"preview":32},"troubleshooting","Troubleshooting",{"slug":95,"title":96,"preview":32},"faq","FAQ",{"slug":98,"title":99,"preview":32},"compatibility","Versioning and compatibility",{"slug":101,"title":102,"preview":32},"field-reference","Field reference",{"slug":104,"title":105,"preview":32},"ai","AI assistants","page",{"title":59,"description":108,"html":109,"headings":110,"editUrl":146,"markdownUrl":147,"prev":148,"next":149},"This page is about e-invoices you receive, for example from suppliers. Quittio reads XML files (CII and UBL, including XRechnung and Peppol) and PDFs with embedded XML (ZUGFeRD, Factur-X).","\u003Ch1 id=\"reading-incoming-invoices\">Reading incoming invoices\u003C\u002Fh1>\n\u003Cp>This page is about e-invoices you receive, for example from suppliers. Quittio reads XML files (CII and UBL, including XRechnung and Peppol) and PDFs with embedded XML (ZUGFeRD, Factur-X). It returns their content in the same data model that you use to build invoices, so you can take the values into your accounting.\u003C\u002Fp>\n\u003Cp>If these formats are new to you, see \u003Ca href=\"\u002Fdocs\u002Fconcepts#formats\">Formats\u003C\u002Fa>, \u003Ca href=\"\u002Fdocs\u002Fconcepts#syntaxes-cii-and-ubl\">Syntaxes\u003C\u002Fa> and \u003Ca href=\"\u002Fdocs\u002Fconcepts#profiles\">Profiles\u003C\u002Fa> in the E-invoicing basics; field numbers such as BT-24 are explained in \u003Ca href=\"\u002Fdocs\u002Fconcepts#en-16931-and-business-terms\">EN 16931 and business terms\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"reading-a-file\">Reading a file\u003Ca class=\"q-doc-anchor\" href=\"#reading-a-file\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cdiv class=\"q-doc-code\">\u003Cdiv class=\"q-doc-code-bar\">\u003Cspan>php\u003C\u002Fspan>\u003Cbutton type=\"button\" class=\"q-doc-copy\" data-copy aria-label=\"Copy code\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\u003Crect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\"\u002F>\u003Cpath d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"\u002F>\u003C\u002Fsvg>\u003Cspan>Copy\u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre class=\"shiki github-dark-default\" style=\"background-color:#0d1117;color:#e6edf3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FF7B72\">use\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\\Laravel\\Facades\\Quittio\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$read \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">::\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">read\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">($request\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">file\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">(\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">'invoice'\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">)\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">get\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">());   \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F content of an uploaded XML or PDF\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$read \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">::\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">readFile\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">(\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">'\u002Fpath\u002Fto\u002Finvoice.pdf'\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">);          \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F or a local file\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$invoice \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> $read\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">data;          \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F InvoiceData as stated in the document\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$invoice\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">number;                \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F e.g. \"RE-2026-0101\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$invoice\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">seller\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">name;          \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F the supplier\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$invoice\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">totals\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">?->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">amountDue;    \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F amount due as stated in the document\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$read\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">profile;                  \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F detected profile key, e.g. \"en16931\" or \"xrechnung\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$read\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">findings;                 \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F problems found while reading, e.g. QUITTIO-DECLARED-TOTALS\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$read\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">declaredTotals;           \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F totals as stated in the document\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$read\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">embeddedFilename;         \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F for PDFs: factur-x.xml, xrechnung.xml, zugferd-invoice.xml …\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>You get back a \u003Ccode>ReadResult\u003C\u002Fcode> (\u003Ca href=\"#the-result\">The result\u003C\u002Fa>):\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode>data\u003C\u002Fcode> is an \u003Ccode>InvoiceData\u003C\u002Fcode> with the values as stated in the document. Amounts are never corrected. Totals that do not match the lines are reported as finding \u003Ccode>QUITTIO-DECLARED-TOTALS\u003C\u002Fcode> (\u003Ca href=\"#declared-amounts\">Declared amounts\u003C\u002Fa>).\u003C\u002Fli>\n\u003Cli>\u003Ccode>findings\u003C\u002Fcode> lists problems found while reading, e.g. a missing issue date (\u003Ca href=\"#findings\">Findings\u003C\u002Fa>).\u003C\u002Fli>\n\u003Cli>\u003Ccode>profile\u003C\u002Fcode> is the profile detected from the document, e.g. \u003Ccode>xrechnung\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Ccode>read()\u003C\u002Fcode> always treats its argument as the content of the document, never as a file name. You can pass request bodies (\u003Ccode>$request-&gt;getContent()\u003C\u002Fcode>) and uploads directly.\u003C\u002Fp>\n\u003Cp>\u003Ccode>readFile()\u003C\u002Fcode> reads a local file. It rejects paths with null bytes, missing or unreadable files, and files larger than the larger of the XML and PDF limits (\u003Ccode>UnreadableInvoiceException\u003C\u002Fcode>).\u003C\u002Fp>\n\u003Cp>Without Laravel, both methods exist on \u003Ccode>Quittio\\Core\\Quittio\u003C\u002Fcode> and use the limits of its configuration (\u003Ca href=\"#limits-and-security\">Limits and security\u003C\u002Fa>). A file that is no supported e-invoice throws an exception (\u003Ca href=\"#errors\">Errors\u003C\u002Fa>).\u003C\u002Fp>\n\u003Ch2 id=\"checking-an-incoming-invoice\">Checking an incoming invoice\u003Ca class=\"q-doc-anchor\" href=\"#checking-an-incoming-invoice\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Reading never validates the whole document. Before you book an invoice, check \u003Ccode>$read-&gt;findings\u003C\u002Fcode>, or validate the file:\u003C\u002Fp>\n\u003Cdiv class=\"q-doc-code\">\u003Cdiv class=\"q-doc-code-bar\">\u003Cspan>php\u003C\u002Fspan>\u003Cbutton type=\"button\" class=\"q-doc-copy\" data-copy aria-label=\"Copy code\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\u003Crect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\"\u002F>\u003Cpath d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"\u002F>\u003C\u002Fsvg>\u003Cspan>Copy\u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre class=\"shiki github-dark-default\" style=\"background-color:#0d1117;color:#e6edf3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FF7B72\">use\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\\Laravel\\Facades\\Quittio\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$report \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">::\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">validateFile\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">($content);   \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F content of an XML or PDF\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$report \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">::\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">validatePath\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">($path);      \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F or a local file\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FF7B72\">if\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> (\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">!\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> $report\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">isValid\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">()) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:6ch;text-indent:-6ch\">\u003Cspan style=\"color:#8B949E\">    \u002F\u002F reject the invoice, e.g. show $report->errors()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>\u003Ccode>validateFile()\u003C\u002Fcode> and \u003Ccode>validatePath()\u003C\u002Fcode> read the file and run all configured validation levels on it (\u003Ca href=\"\u002Fdocs\u002Fvalidation#incoming-files\">Incoming files\u003C\u002Fa>). A complete controller that validates an upload and extracts the values for accounting is in \u003Ca href=\"\u002Fdocs\u002Fexamples#incoming-e-invoices\">Incoming e-invoices\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"on-the-command-line\">On the command line\u003Ca class=\"q-doc-anchor\" href=\"#on-the-command-line\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cdiv class=\"q-doc-code\">\u003Cdiv class=\"q-doc-code-bar\">\u003Cspan>bash\u003C\u002Fspan>\u003Cbutton type=\"button\" class=\"q-doc-copy\" data-copy aria-label=\"Copy code\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\u003Crect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\"\u002F>\u003Cpath d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"\u002F>\u003C\u002Fsvg>\u003Cspan>Copy\u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre class=\"shiki github-dark-default\" style=\"background-color:#0d1117;color:#e6edf3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FFA657\">php\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> artisan\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> quittio:read\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> invoice.pdf\u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">          # number, date, type, syntax and profile, parties, lines, totals, findings\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FFA657\">php\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> artisan\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> quittio:read\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> invoice.xml\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> --json\u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">   # InvoiceData as JSON\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FFA657\">php\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> artisan\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> quittio:validate\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> invoice.pdf\u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">      # validation report\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>See \u003Ca href=\"\u002Fdocs\u002Fcommands#quittioread\">quittio:read\u003C\u002Fa> and \u003Ca href=\"\u002Fdocs\u002Fcommands#quittiovalidate\">quittio:validate\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"supported-documents\">Supported documents\u003Ca class=\"q-doc-anchor\" href=\"#supported-documents\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Ctable class=\"q-doc-table q-stack-table\">\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Input\u003C\u002Fth>\n\u003Cth>Recognised by\u003C\u002Fth>\n\u003Cth>Syntax\u003C\u002Fth>\n\u003Cth>Content\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>CII XML\u003C\u002Ftd>\n\u003Ctd data-label=\"Recognised by\">root \u003Ccode>CrossIndustryInvoice\u003C\u002Fcode> in \u003Ccode>urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Syntax\">\u003Ccode>cii\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">ZUGFeRD 2.x \u002F Factur-X MINIMUM, BASIC WL, BASIC, EN 16931, EXTENDED; XRechnung CII including the extension\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>UBL XML\u003C\u002Ftd>\n\u003Ctd data-label=\"Recognised by\">root \u003Ccode>Invoice\u003C\u002Fcode> or \u003Ccode>CreditNote\u003C\u002Fcode> in the UBL 2.1 namespaces\u003C\u002Ftd>\n\u003Ctd data-label=\"Syntax\">\u003Ccode>ubl\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">EN 16931, XRechnung UBL including the extension, Peppol BIS Billing 3.0\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>PDF\u003C\u002Ftd>\n\u003Ctd data-label=\"Recognised by\">content starts with \u003Ccode>%PDF\u003C\u002Fcode> (leading whitespace allowed)\u003C\u002Ftd>\n\u003Ctd data-label=\"Syntax\">of the embedded XML\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">ZUGFeRD 2.x \u002F Factur-X, XRechnung embedded in a PDF\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>Everything else fails:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>ZUGFeRD 1.0 (\u003Ccode>urn:ferd:CrossIndustryDocument:invoice:1p0\u003C\u002Fcode>) does not conform to EN 16931 and is rejected with a clear message.\u003C\u002Fli>\n\u003Cli>Other root elements fail with &quot;Unknown invoice format&quot;.\u003C\u002Fli>\n\u003Cli>PDFs without embedded invoice fail with &quot;The PDF does not contain an embedded e-invoice&quot;.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>The profile is detected from the specification identifier (BT-24). In CII it is \u003Ccode>GuidelineSpecifiedDocumentContextParameter\u003C\u002Fcode>, in UBL \u003Ccode>cbc:CustomizationID\u003C\u002Fcode>. Quittio compares it exactly with the identifiers of the installed profiles, for EN 16931:2017 and EN 16931:2026. Country pack profiles such as XRechnung count once the pack is registered.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>An unknown identifier leaves \u003Ccode>profile\u003C\u002Fcode> \u003Ccode>null\u003C\u002Fcode> and is reported as information (\u003Ccode>QUITTIO-READER-UNKNOWN-PROFILE\u003C\u002Fcode>).\u003C\u002Fli>\n\u003Cli>An identifier starting with \u003Ccode>urn:cen.eu:en16931:2026\u003C\u002Fcode> sets the standard version of the data to EN 16931:2026.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"errors\">Errors\u003Ca class=\"q-doc-anchor\" href=\"#errors\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>The reader throws an exception only when it cannot read the document at all:\u003C\u002Fp>\n\u003Ctable class=\"q-doc-table q-stack-table\">\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Exception\u003C\u002Fth>\n\u003Cth>When\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>Quittio\\Core\\Xml\\UnsafeXmlException\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"When\">The XML is too large, not well-formed, has a DOCTYPE, an unsupported encoding or exceeds a tag limit\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>Quittio\\Core\\Pdf\\PdfException\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"When\">The PDF is too large, encrypted, malformed, exceeds a structure or decompression limit or uses an unsupported stream filter\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>Quittio\\Core\\Reading\\UnreadableInvoiceException\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"When\">Unknown format, ZUGFeRD 1.0, a PDF without embedded invoice, a file that does not exist, is not readable or is too large\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>All three implement \u003Ccode>Quittio\\Core\\Exceptions\\QuittioException\u003C\u002Fcode>. \u003Ccode>validateFile()\u003C\u002Fcode> and \u003Ccode>validatePath()\u003C\u002Fcode> throw the same exceptions. Everything the reader can read becomes a finding instead.\u003C\u002Fp>\n\u003Ch2 id=\"the-result\">The result\u003Ca class=\"q-doc-anchor\" href=\"#the-result\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>\u003Ccode>Quittio\\Core\\Reading\\ReadResult\u003C\u002Fcode> (readonly):\u003C\u002Fp>\n\u003Ctable class=\"q-doc-table q-stack-table\">\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Property\u003C\u002Fth>\n\u003Cth>Content\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>data\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">\u003Ccode>InvoiceData\u003C\u002Fcode> as stated: lines with their declared net amounts, the declared totals and VAT breakdown, all other business terms\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>syntax\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">\u003Ccode>cii\u003C\u002Fcode> or \u003Ccode>ubl\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>specificationId\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">BT-24 as written, or \u003Ccode>null\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>profile\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">key of the detected profile (\u003Ccode>en16931\u003C\u002Fcode>, \u003Ccode>extended\u003C\u002Fcode>, \u003Ccode>xrechnung\u003C\u002Fcode>, \u003Ccode>peppol\u003C\u002Fcode> …) or \u003Ccode>null\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>declaredTotals\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">\u003Ccode>Totals\u003C\u002Fcode> as stated (BT-106 to BT-115), \u003Ccode>null\u003C\u002Fcode> if the document has no monetary summation\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>declaredVatBreakdown\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">\u003Ccode>list&lt;VatBreakdown&gt;\u003C\u002Fcode> as stated (BG-23)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>findings\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">\u003Ccode>list&lt;ValidationMessage&gt;\u003C\u002Fcode> (see \u003Ca href=\"#findings\">Findings\u003C\u002Fa>)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>xml\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">the XML that was read (for a PDF: the embedded XML)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>raw\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">the input: the PDF bytes, or the XML\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>embeddedFilename\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Content\">name of the embedded file for PDFs, otherwise \u003Ccode>null\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>\u003Ccode>hasFindings()\u003C\u002Fcode> tells whether there are findings. Extended data is read into the same data model as when building invoices (\u003Ca href=\"\u002Fdocs\u002Ffield-reference\">field reference\u003C\u002Fa>): Factur-X EXTENDED, sub lines from \u003Ccode>ParentLineID\u003C\u002Fcode> or \u003Ccode>cac:SubInvoiceLine\u003C\u002Fcode>, and XRechnung third party payments.\u003C\u002Fp>\n\u003Ch3 id=\"declared-amounts\">Declared amounts\u003Ca class=\"q-doc-anchor\" href=\"#declared-amounts\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh3>\n\u003Cp>Totals are never corrected silently. The reader keeps the amounts as stated and recalculates a copy from the lines. Every difference is reported as \u003Ccode>QUITTIO-DECLARED-TOTALS\u003C\u002Fcode> (warning, level L3). It compares:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>the net amount of every line (BT-131),\u003C\u002Fli>\n\u003Cli>the sum of line net amounts (BT-106), the total without VAT (BT-109), the VAT total (BT-110), the total with VAT (BT-112) and the amount due (BT-115).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Documents without lines (Factur-X MINIMUM, BASIC WL) are not recalculated. MINIMUM does not transmit BT-106; it is derived from BT-109, BT-107 and BT-108 (\u003Ccode>QUITTIO-READER-DERIVED\u003C\u002Fcode>).\u003C\u002Fp>\n\u003Cp>EN 16931 carries the VAT exemption reason (BT-120, BT-121) only on the VAT breakdown. The reader copies it back to the lines, allowances and charges of the VAT group, so a recalculation keeps it.\u003C\u002Fp>\n\u003Cp>A read invoice can be the start of a builder (\u003Ccode>InvoiceBuilder::from($read-&gt;data)\u003C\u002Fcode>) or be cancelled (\u003Ca href=\"\u002Fdocs\u002Fbuilding-invoices\">Building invoices\u003C\u002Fa>). To keep its declared amounts there, the reader stamps a fingerprint of the amount inputs into the meta data (\u003Ccode>$read-&gt;data-&gt;meta-&gt;amountsFingerprint()\u003C\u002Fcode>). As long as lines, prices, allowances, charges, VAT breakdown and currency are unchanged, \u003Ccode>InvoiceBuilder::from($read-&gt;data)\u003C\u002Fcode> and cancellations of the read invoice keep:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>declared line net amounts within 0.02 of quantity × price ± allowances and charges,\u003C\u002Fli>\n\u003Cli>declared VAT amounts less than one currency unit from the recalculation, e.g. when another system rounded per line.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Data changed before (e.g. with \u003Ccode>with()\u003C\u002Fcode>) no longer matches the fingerprint and is recalculated completely. \u003Ccode>Quittio::make($read-&gt;data)\u003C\u002Fcode> recalculates everything.\u003C\u002Fp>\n\u003Cp>The price base quantity (BT-149, BT-150) is read from the net price, or from the gross price if only the gross price states it. If both state different base quantities (CII), the gross price and discount are converted to the base quantity of the net price. With different units they are kept as stated, and a warning is reported.\u003C\u002Fp>\n\u003Ch2 id=\"findings\">Findings\u003Ca class=\"q-doc-anchor\" href=\"#findings\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>The reader is tolerant: it reads as much of the document as possible and reports problems as findings instead of failing. Codes starting with \u003Ccode>BR-\u003C\u002Fcode> are the EN 16931 rules that the problem breaks (\u003Ca href=\"\u002Fdocs\u002Fconcepts#rules-and-validation\">Rules and validation\u003C\u002Fa>). Findings have level L1 unless noted. Errors mean that values are missing or could not be read as stated:\u003C\u002Fp>\n\u003Ctable class=\"q-doc-table q-stack-table\">\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Code\u003C\u002Fth>\n\u003Cth>Severity\u003C\u002Fth>\n\u003Cth>Meaning\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>BR-03\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The issue date (BT-2) is missing or unreadable. The placeholder \u003Ccode>1970-01-01\u003C\u002Fcode> is used, never the current date.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>BR-05\u003C\u002Fcode>, \u003Ccode>BR-CL-04\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The invoice currency (BT-5) is missing or not an ISO 4217 code. The amounts are read in the currency of the amounts, otherwise in \u003Ccode>XXX\u003C\u002Fcode> (no currency).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-CURRENCY\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error \u002F warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">Amounts use another currency than BT-5 and are read as BT-5 (error); only the VAT total in accounting currency (BT-111) may differ. In CII a BT-110 without \u003Ccode>currencyID\u003C\u002Fcode> is read in the invoice currency (warning).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-EXCHANGE-RATE\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The exchange rate (CII) converts other currencies than BT-5 and BT-6.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-DATE\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A date is not in the format of the syntax: CII format 102 (\u003Ccode>YYYYMMDD\u003C\u002Fcode>), UBL \u003Ccode>YYYY-MM-DD\u003C\u002Fcode> with an optional time zone. The date is not read.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-NUMBER\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A number is not a decimal number (exponents like \u003Ccode>1e3\u003C\u002Fcode>, separators, more than 40 characters) or a payment term period is no whole number. The value is not read.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>BR-DEC-…\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">An amount whose business term has a BR-DEC rule has more than two decimals. It is rounded to two decimals.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-DECIMALS\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">Another amount has more than two decimals and is rounded.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>BR-12\u003C\u002Fcode> … \u003Ccode>BR-15\u003C\u002Fcode>, \u003Ccode>BR-45\u003C\u002Fcode>, \u003Ccode>BR-46\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A mandatory amount (BT-106, BT-109, BT-112, BT-115, BT-116, BT-117) is missing; 0.00 is used. Without the document totals (BG-22: CII \u003Ccode>SpecifiedTradeSettlementHeaderMonetarySummation\u003C\u002Fcode>, UBL \u003Ccode>LegalMonetaryTotal\u003C\u002Fcode>) \u003Ccode>BR-12\u003C\u002Fcode> (only with lines) to \u003Ccode>BR-15\u003C\u002Fcode> are reported and \u003Ccode>data-&gt;totals\u003C\u002Fcode> and \u003Ccode>declaredTotals\u003C\u002Fcode> stay \u003Ccode>null\u003C\u002Fcode>; \u003Ccode>validateFile()\u003C\u002Fcode> then reports these instead of \u003Ccode>QUITTIO-NOT-CALCULATED\u003C\u002Fcode>.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-DERIVED\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">info\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">BT-106 was derived for a document without lines.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>BR-22\u003C\u002Fcode>, \u003Ccode>BR-23\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A line has no quantity (0 is used) or no unit.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-SUBLINE-QUANTITY\u003C\u002Fcode>, \u003Ccode>QUITTIO-READER-SUBLINE-UNIT\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">info\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A sub line of the extension omits quantity or unit.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-DUPLICATE-LINE\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A line identifier is used more than once (CII).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-PARENT-LINE\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning \u002F error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A sub line refers to a parent line that does not exist (warning), to itself, to a cycle or to a hierarchy deeper than 32 levels (error); it is read as a top-level line (CII).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-BASE-QUANTITY\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">info \u002F warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">Net and gross price state different base quantities (CII): converted (info) or not convertible (warning).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-VAT-CATEGORY\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">error\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">Unknown VAT category; \u003Ccode>S\u003C\u002Fcode> is assumed.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-UNKNOWN-CODE\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">info \u002F warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A code that this package version does not know (unit, scheme, reason codes …) is kept as raw value (info); a VAT point date code outside the code list (warning). Codes of the official code lists without an enum case are read without finding.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-UNIT\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A payment terms period is not given in days or weeks (CII); weeks are converted to days.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-INSTALLMENT\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">A partial payment (EXTENDED) without due date is skipped.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-ATTACHMENT\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">An attached document has invalid Base64, an unsupported MIME code or no usable file name and is skipped.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-UNKNOWN-PROFILE\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">info\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The specification identifier (BT-24) is not known to this installation.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-PDF-CANDIDATES\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The PDF embeds several invoice files with different content, or several XML files without a known name; the chosen file is named.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-PDF-AF\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The embedded file is not an associated file (\u003Ccode>\u002FAF\u003C\u002Fcode>), as PDF\u002FA-3 requires.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-PDF-RELATIONSHIP\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The \u003Ccode>\u002FAFRelationship\u003C\u002Fcode> of the embedded file does not match the profile (\u003Ccode>Alternative\u003C\u002Fcode>, or \u003Ccode>Data\u003C\u002Fcode> for MINIMUM and BASIC WL).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-DECLARED-TOTALS\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning (L3)\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The declared amounts differ from a recalculation from the lines.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>QUITTIO-READER-RECALCULATION\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd data-label=\"Severity\">warning (L3)\u003C\u002Ftd>\n\u003Ctd data-label=\"Meaning\">The invoice could not be recalculated for the comparison.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>Unknown codes are errors in \u003Ccode>validateFile()\u003C\u002Fcode>, where the code list rules (\u003Ccode>BR-CL-…\u003C\u002Fcode>) run.\u003C\u002Fp>\n\u003Ch2 id=\"pdf\">PDF\u003Ca class=\"q-doc-anchor\" href=\"#pdf\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>A ZUGFeRD or Factur-X PDF carries the invoice XML as embedded file (\u003Ca href=\"\u002Fdocs\u002Fformats#embedded-files\">Embedded files\u003C\u002Fa>). The reader finds embedded files in the associated files (\u003Ccode>\u002FAF\u003C\u002Fcode>) of the document catalog and in the name tree (\u003Ccode>\u002FNames \u002FEmbeddedFiles\u003C\u002Fcode>). This works also in PDFs with cross-reference streams, object streams, hybrid files and incremental updates. Damaged cross-reference data is rebuilt by scanning the file.\u003C\u002Fp>\n\u003Cp>The file is chosen in this order:\u003C\u002Fp>\n\u003Col>\n\u003Cli>A known file name (\u003Ccode>factur-x.xml\u003C\u002Fcode>, \u003Ccode>xrechnung.xml\u003C\u002Fcode>, \u003Ccode>zugferd-invoice.xml\u003C\u002Fcode>, \u003Ccode>ZUGFeRD-invoice.xml\u003C\u002Fcode>, case-insensitive) before any other \u003Ccode>.xml\u003C\u002Fcode> file.\u003C\u002Fli>\n\u003Cli>Among those, files referenced from \u003Ccode>\u002FAF\u003C\u002Fcode> before files only in the name tree.\u003C\u002Fli>\n\u003Cli>Then the order of the known names and of the document.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Up to three further candidates with a known name are compared with the chosen file; different content is reported (\u003Ccode>QUITTIO-READER-PDF-CANDIDATES\u003C\u002Fcode>).\u003C\u002Fp>\n\u003Cp>Encrypted PDFs cannot be read. Streams must use \u003Ccode>FlateDecode\u003C\u002Fcode> (with PNG or TIFF predictors) or no filter.\u003C\u002Fp>\n\u003Ch2 id=\"limits-and-security\">Limits and security\u003Ca class=\"q-doc-anchor\" href=\"#limits-and-security\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Incoming files come from outside, so the reader limits what it accepts:\u003C\u002Fp>\n\u003Ctable class=\"q-doc-table q-stack-table\">\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Protection\u003C\u002Fth>\n\u003Cth>Limit\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>XML size\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">\u003Ccode>quittio.reader.max_xml_bytes\u003C\u002Fcode> (10 MB); without Laravel \u003Ccode>reader.max_xml_bytes\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>PDF size\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">\u003Ccode>quittio.reader.max_pdf_bytes\u003C\u002Fcode> (25 MB)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Decompressed size of every PDF stream\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">\u003Ccode>quittio.reader.max_decompressed_bytes\u003C\u002Fcode> (50 MB)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>DOCTYPE\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">Rejected (also an internal subset), so there are no external entities, no DTDs and no entity expansion; libxml runs without network access and without entity substitution\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Encoding\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">UTF-8, UTF-16, US-ASCII, ISO-8859-\u003Cem>, Windows-125\u003C\u002Fem>; UTF-32, UTF-7, EBCDIC and other encodings are rejected\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Start tags\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">at most 64 KB and 256 attributes per element, at most 256 namespace declarations in scope (checked before parsing)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Numbers\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">decimal literals of at most 40 characters, no exponents\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>PDF structure\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">at most 1,000,000 objects, 100 cross-reference sections, reference chains of 32, 100,000 objects per object stream, 100,000 objects when rebuilding, nesting depth 64; name tree depth 10 and 1,000 nodes, 1,000 file specifications, every node visited once\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Sub lines\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">hierarchies deeper than 32 levels are flattened (CII)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>File names\u003C\u002Ftd>\n\u003Ctd data-label=\"Limit\">embedded file names and attachment file names are never used as paths: directory parts and control and format characters (e.g. a right-to-left override) are removed, \u003Ccode>.\u003C\u002Fcode>, \u003Ccode>..\u003C\u002Fcode> and empty names are rejected\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>Untrusted values are shortened in messages, and the currency of amounts is compared in PHP, never inside an XPath expression. The configuration keys are described in \u003Ca href=\"\u002Fdocs\u002Fconfiguration#reader\">Reader\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"own-readers\">Own readers\u003Ca class=\"q-doc-anchor\" href=\"#own-readers\" aria-label=\"Link to this section\">#\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>\u003Ccode>Quittio\\Core\\Reading\\InvoiceReader\u003C\u002Fcode> can be used directly:\u003C\u002Fp>\n\u003Cdiv class=\"q-doc-code\">\u003Cdiv class=\"q-doc-code-bar\">\u003Cspan>php\u003C\u002Fspan>\u003Cbutton type=\"button\" class=\"q-doc-copy\" data-copy aria-label=\"Copy code\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\u003Crect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\"\u002F>\u003Cpath d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"\u002F>\u003C\u002Fsvg>\u003Cspan>Copy\u003C\u002Fspan>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre class=\"shiki github-dark-default\" style=\"background-color:#0d1117;color:#e6edf3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FF7B72\">use\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\\Core\\Pdf\\PdfEmbeddedFileExtractor\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#FF7B72\">use\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> Quittio\\Core\\Reading\\InvoiceReader\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$reader \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\"> new\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> InvoiceReader\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:6ch;text-indent:-6ch\">\u003Cspan style=\"color:#FFA657\">    readers\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\">null\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">,                                                   \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F null = InvoiceReader::defaultReaders(): CII and UBL\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:6ch;text-indent:-6ch\">\u003Cspan style=\"color:#FFA657\">    profiles\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\">null\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">,                                                  \u003C\u002Fspan>\u003Cspan style=\"color:#8B949E\">\u002F\u002F null = ProfileRegistry::withDefaults() (no country pack profiles)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:6ch;text-indent:-6ch\">\u003Cspan style=\"color:#FFA657\">    pdfExtractor\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">: \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">new\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> PdfEmbeddedFileExtractor\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">(\u003C\u002Fspan>\u003Cspan style=\"color:#FFA657\">maxPdfBytes\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\">25\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> 1024\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> 1024\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">, \u003C\u002Fspan>\u003Cspan style=\"color:#FFA657\">maxDecompressedBytes\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\">50\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> 1024\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> 1024\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">),\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:6ch;text-indent:-6ch\">\u003Cspan style=\"color:#FFA657\">    maxXmlBytes\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\">10\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> 1024\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\"> *\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> 1024\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\" style=\"padding-left:2ch;text-indent:-2ch\">\u003Cspan style=\"color:#E6EDF3\">$read \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> $reader\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">withReader\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">(\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">new\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> MyFormatReader\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">)\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">->\u003C\u002Fspan>\u003Cspan style=\"color:#D2A8FF\">readFile\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">(\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">'\u002Fpath\u002Fto\u002Finvoice.xml'\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">);\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>A reader for another XML format implements \u003Ccode>FormatReader\u003C\u002Fcode> (\u003Ccode>canRead(DOMDocument $document): bool\u003C\u002Fcode>, \u003Ccode>read(DOMDocument $document, string $xml): ReadResult\u003C\u002Fcode>). \u003Ccode>withReader()\u003C\u002Fcode> returns a copy with the reader added after the default ones.\u003C\u002Fp>\n\u003Cp>Country packs provide readers for national formats with \u003Ccode>CountryPack::readers()\u003C\u002Fcode>. It returns new instances on every call, because readers keep the state of one document. \u003Ccode>Quittio::read()\u003C\u002Fcode>, \u003Ccode>readFile()\u003C\u002Fcode>, \u003Ccode>validateFile()\u003C\u002Fcode> and \u003Ccode>validatePath()\u003C\u002Fcode> try them after the CII and UBL readers, for every registered pack. The XSD driver (L4) knows only CII and UBL and reports other root elements (\u003Ccode>XSD-UNKNOWN-ROOT\u003C\u002Fcode>); add a validator for a national format with \u003Ccode>addValidator()\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>A PDF extractor implements one of two interfaces:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode>EmbeddedXmlExtractor::extract(string $pdf): ?array\u003C\u002Fcode> returns file name and XML,\u003C\u002Fli>\n\u003Cli>\u003Ccode>DiagnosingXmlExtractor::extractFile(string $pdf): ?ExtractedXml\u003C\u002Fcode> returns \u003Ccode>filename\u003C\u002Fcode>, \u003Ccode>xml\u003C\u002Fcode>, \u003Ccode>relationship\u003C\u002Fcode> and \u003Ccode>findings\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Ccode>PdfEmbeddedFileExtractor::names($pdf)\u003C\u002Fcode> lists the names of all embedded files.\u003C\u002Fp>\n",[111,115,118,121,124,127,130,134,137,140,143],{"id":112,"text":113,"level":114},"reading-a-file","Reading a file",2,{"id":116,"text":117,"level":114},"checking-an-incoming-invoice","Checking an incoming invoice",{"id":119,"text":120,"level":114},"on-the-command-line","On the command line",{"id":122,"text":123,"level":114},"supported-documents","Supported documents",{"id":125,"text":126,"level":114},"errors","Errors",{"id":128,"text":129,"level":114},"the-result","The result",{"id":131,"text":132,"level":133},"declared-amounts","Declared amounts",3,{"id":135,"text":136,"level":114},"findings","Findings",{"id":138,"text":139,"level":114},"pdf","PDF",{"id":141,"text":142,"level":114},"limits-and-security","Limits and security",{"id":144,"text":145,"level":114},"own-readers","Own readers","https:\u002F\u002Fgithub.com\u002FQuittio\u002Fquittio\u002Fedit\u002Fmaster\u002Fdocs\u002Freading.md","\u002Fdocs\u002Freading.md",{"slug":55,"title":56},{"slug":61,"title":62}]