<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>speedata news</title>
    <link>https://news.speedata.de/</link>
    <description>Recent content on speedata news</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-en</language>
    <copyright>This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.</copyright>
    <lastBuildDate>Tue, 24 Feb 2026 10:00:00 +0100</lastBuildDate>
    
        <atom:link href="https://news.speedata.de/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Version 5.4 released</title>
      <link>https://news.speedata.de/2026/02/24/version-5_4_released/</link>
      <pubDate>Tue, 24 Feb 2026 10:00:00 +0100</pubDate>
      
      <guid>https://news.speedata.de/2026/02/24/version-5_4_released/</guid>
      <description>&lt;p&gt;Version 5.4 of the &lt;a href=&#34;https://www.speedata.de/&#34;&gt;speedata Publisher&lt;/a&gt; is now available. This is a solid update with speed improvements, better HTML support, and a few nice additions. Here is what changed since 5.2.&lt;/p&gt;
&lt;h2 id=&#34;speed&#34;&gt;Speed&lt;/h2&gt;
&lt;p&gt;This version is noticeably faster. Several internal optimizations — grid allocation, paragraph post-processing, and general typesetting — add up to a real difference, especially for larger documents. There is also a new option &lt;code&gt;html=&amp;quot;off&amp;quot;&lt;/code&gt; on text elements to skip the HTML parser when you do not need it, which speeds things up further.&lt;/p&gt;
&lt;h2 id=&#34;letterspacing&#34;&gt;Letterspacing&lt;/h2&gt;
&lt;p&gt;You can now set letter spacing in &lt;code&gt;&amp;lt;Textformat&amp;gt;&lt;/code&gt;. This has been requested a few times, especially for headings and display text.&lt;/p&gt;
&lt;h2 id=&#34;section-element&#34;&gt;Section element&lt;/h2&gt;
&lt;p&gt;A new &lt;code&gt;&amp;lt;Section&amp;gt;&lt;/code&gt; element lets you group parts of your layout file. It does not affect the output — it is purely for organization. The new &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=speedata.vscode-speedata&#34;&gt;vscode-speedata extension&lt;/a&gt; uses it for code folding and outline navigation. More about this in the &lt;a href=&#34;https://news.speedata.de/2026/02/23/section-element/&#34;&gt;previous blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;html-and-css&#34;&gt;HTML and CSS&lt;/h2&gt;
&lt;p&gt;Many improvements in this area:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better table handling (borders, splitting, empty tables)&lt;/li&gt;
&lt;li&gt;More list style types&lt;/li&gt;
&lt;li&gt;Font family normalization&lt;/li&gt;
&lt;li&gt;CSS font size setting via &lt;code&gt;cssfontsize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Various border and color fixes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;bug-fixes&#34;&gt;Bug fixes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Fix margin protrusion values&lt;/li&gt;
&lt;li&gt;Fix infinite loops in HTML tables and paragraph post-processing&lt;/li&gt;
&lt;li&gt;Fix &lt;code&gt;ForAll&lt;/code&gt; context loss with the new XPath parser&lt;/li&gt;
&lt;li&gt;Fix absolute positioning height calculation&lt;/li&gt;
&lt;li&gt;Fix &lt;code&gt;Until&lt;/code&gt; with new XPath mode&lt;/li&gt;
&lt;li&gt;Set correct exit code when errors occur&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;vscode-extension&#34;&gt;VSCode extension&lt;/h2&gt;
&lt;p&gt;The new &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=speedata.vscode-speedata&#34;&gt;vscode-speedata&lt;/a&gt; extension replaces the older RedHat XML setup. It brings proper syntax support, validation, autocomplete, and the Section-based code folding mentioned above.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;As always, downloads are at &lt;a href=&#34;https://download.speedata.de&#34;&gt;download.speedata.de&lt;/a&gt;. The &lt;a href=&#34;https://doc.speedata.de/publisher/en/changelog/#ch-changelog&#34;&gt;detailed changelog&lt;/a&gt; is in the manual.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Structuring layouts with the new Section element</title>
      <link>https://news.speedata.de/2026/02/23/section-element/</link>
      <pubDate>Mon, 23 Feb 2026 09:00:00 +0100</pubDate>
      
      <guid>https://news.speedata.de/2026/02/23/section-element/</guid>
      <description>&lt;p&gt;Layout files in the speedata Publisher can get long. Really long. A product catalog with conditional page types, fallback logic, index generation, and a dozen different record types easily grows to a few hundred lines of XML. And at that point, scrolling through the file becomes a chore.&lt;/p&gt;
&lt;p&gt;I have been wanting a way to organize layout code into logical groups for a while — something like regions or sections that you can collapse and navigate. The problem: any new element in the layout language usually &lt;em&gt;does&lt;/em&gt; something. It affects the output, it changes behavior, it needs to be documented and tested and maintained.&lt;/p&gt;
&lt;p&gt;So I added an element that does nothing.&lt;/p&gt;
&lt;h2 id=&#34;the-section-element&#34;&gt;The Section element&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;Section&amp;gt;&lt;/code&gt; is a new element in the speedata Publisher layout language. It has one attribute: &lt;code&gt;name&lt;/code&gt;. It wraps other elements. And that is all it does.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;Layout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;na&#34;&gt;xmlns=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;urn:speedata.de:2009/publisher/en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;na&#34;&gt;xmlns:sd=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;urn:speedata:2009/publisher/functions/en&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Section&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Font definitions&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;LoadFontfile&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;DefineFontfamily&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Section&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Section&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Page types&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;Pagetype&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;test=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;true()&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Pagetype&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Section&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Section&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Data processing&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;Record&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;element=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;catalog&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Record&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Section&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Layout&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The speedata Publisher simply ignores &lt;code&gt;&amp;lt;Section&amp;gt;&lt;/code&gt; during processing. It does not create a scope, it does not affect variables, it does not change page handling or anything else. The PDF output is identical whether you use sections or not.&lt;/p&gt;
&lt;p&gt;So why bother?&lt;/p&gt;
&lt;h2 id=&#34;code-folding-and-outline&#34;&gt;Code folding and outline&lt;/h2&gt;
&lt;p&gt;The real benefit shows up in the editor. The new &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=speedata.vscode-speedata&#34;&gt;vscode-speedata&lt;/a&gt; extension for Visual Studio Code understands &lt;code&gt;&amp;lt;Section&amp;gt;&lt;/code&gt; elements and uses them for two things:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code folding.&lt;/strong&gt; You can collapse a section and hide everything inside it. When your layout has 2000 lines and you are working on the data processing part, you can fold away the font definitions, the page types, and whatever else you are not interested in right now.&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2026/02/23/section-element/codefolding.png&#34;  /&gt;
        
    
    
&lt;/figure&gt;


&lt;p&gt;&lt;strong&gt;Outline symbols.&lt;/strong&gt; The VS Code outline panel (and the breadcrumb bar) shows your sections as a navigable tree. Instead of scrolling through the file looking for the right &lt;code&gt;&amp;lt;Record&amp;gt;&lt;/code&gt; element, you click on &amp;ldquo;Data processing&amp;rdquo; in the outline and jump right there.&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2026/02/23/section-element/outline.png&#34;  /&gt;
        
    
    
&lt;/figure&gt;


&lt;p&gt;This is a small thing, but it makes a noticeable difference when you work with larger layouts. You spend less time navigating and more time actually editing.&lt;/p&gt;
&lt;h2 id=&#34;the-speedata-vscode-extension&#34;&gt;The speedata-vscode extension&lt;/h2&gt;
&lt;p&gt;The Section support is part of the new &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=speedata.vscode-speedata&#34;&gt;vscode-speedata&lt;/a&gt; extension, which replaces the older RedHat XML mode. Besides sections, it brings proper syntax support, validation, and autocomplete for the speedata Publisher layout language. If you use VS Code for editing your layouts, it is worth installing.&lt;/p&gt;
&lt;h2 id=&#34;do-i-need-to-restructure-my-layouts&#34;&gt;Do I need to restructure my layouts?&lt;/h2&gt;
&lt;p&gt;No. &lt;code&gt;&amp;lt;Section&amp;gt;&lt;/code&gt; is entirely optional. Existing layouts work exactly as before. You can add sections gradually, wherever you feel they help — or not at all. There is no performance cost and no behavioral change.&lt;/p&gt;
&lt;p&gt;If you do want to add them, I would suggest starting with the obvious top-level groups: font definitions, page types, and record handlers. That alone gives you a nice outline and makes folding useful immediately.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;The Section element is available in the current development version of the speedata Publisher. The vscode-speedata extension is available on the &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=speedata.vscode-speedata&#34;&gt;VS Code Marketplace&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>I benchmarked 6 PDF engines — the fastest is not the one I’d pick</title>
      <link>https://news.speedata.de/2026/02/10/typesetting-benchmark/</link>
      <pubDate>Tue, 10 Feb 2026 15:02:22 +0100</pubDate>
      
      <guid>https://news.speedata.de/2026/02/10/typesetting-benchmark/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m building a typesetting engine for a living (&lt;a href=&#34;https://www.speedata.de&#34;&gt;speedata Publisher&lt;/a&gt;). People keep asking me &amp;ldquo;why not just use Typst?&amp;rdquo; or &amp;ldquo;isn&amp;rsquo;t WeasyPrint good enough?&amp;rdquo; and I never had a good answer with real numbers. Just gut feeling. So I decided to actually measure it.&lt;/p&gt;
&lt;p&gt;I set up a simple benchmark, same document with all six tools. And what I learned was maybe not what I expected.&lt;/p&gt;
&lt;h2 id=&#34;the-setup&#34;&gt;The setup&lt;/h2&gt;
&lt;p&gt;The task is simple: a mail merge. You have an XML file with name and address records, you fill in a letter template, and you get a PDF out. One page per letter, with a logo, sender info, recipient address, and some body text. Nothing special, really every tool should be able to do this.&lt;/p&gt;
&lt;p&gt;I tested with 1 record and with 500 records. All templates produce more or less the same visual output. Same A4 page, same Helvetica (or the similar TeX Gyre Heros clone), same logo, same layout with the sender on the right side and body text at 105mm width with hyphenation turned on.&lt;/p&gt;
&lt;p&gt;The tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;speedata Publisher (sp) — my own engine, written in Go, Lua which uses LuaTeX in the background&lt;/li&gt;
&lt;li&gt;Typst — the new kid, written in Rust, has native XML support&lt;/li&gt;
&lt;li&gt;pdflatex — the classic, with Python/Jinja2 for the templating&lt;/li&gt;
&lt;li&gt;LuaLaTeX — basically pdflatex but with Lua scripting and a more modern font system, also with Python/Jinja2&lt;/li&gt;
&lt;li&gt;WeasyPrint — HTML/CSS to PDF, Python based&lt;/li&gt;
&lt;li&gt;Apache FOP — the enterprise XML/XSL-FO thing, Java&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All benchmarks ran with &lt;a href=&#34;https://github.com/sharkdp/hyperfine&#34;&gt;hyperfine&lt;/a&gt; on a macBook air M4 (16 GB). You can find the full setup &lt;a href=&#34;https://github.com/speedata/typesetting-benchmark&#34;&gt;on GitHub&lt;/a&gt; if you want to try it yourself.&lt;/p&gt;
&lt;h2 id=&#34;the-numbers&#34;&gt;The numbers&lt;/h2&gt;
&lt;h3 id=&#34;1-page&#34;&gt;1 page&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Tool&lt;/th&gt;
          &lt;th&gt;Time&lt;/th&gt;
          &lt;th&gt;Relative&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;sp&lt;/td&gt;
          &lt;td&gt;95 ms&lt;/td&gt;
          &lt;td&gt;1.0x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Typst&lt;/td&gt;
          &lt;td&gt;106 ms&lt;/td&gt;
          &lt;td&gt;1.1x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;pdflatex&lt;/td&gt;
          &lt;td&gt;329 ms&lt;/td&gt;
          &lt;td&gt;3.5x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;WeasyPrint&lt;/td&gt;
          &lt;td&gt;335 ms&lt;/td&gt;
          &lt;td&gt;3.5x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;LuaLaTeX&lt;/td&gt;
          &lt;td&gt;519 ms&lt;/td&gt;
          &lt;td&gt;5.5x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Apache FOP&lt;/td&gt;
          &lt;td&gt;532 ms&lt;/td&gt;
          &lt;td&gt;5.6x&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;With one page, sp and Typst are basically the same. Both under 110ms. Everything else is 3.5 to 5.6 times slower.&lt;/p&gt;
&lt;h3 id=&#34;500-pages&#34;&gt;500 pages&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Tool&lt;/th&gt;
          &lt;th&gt;Time&lt;/th&gt;
          &lt;th&gt;Per page&lt;/th&gt;
          &lt;th&gt;Relative&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Typst&lt;/td&gt;
          &lt;td&gt;157 ms&lt;/td&gt;
          &lt;td&gt;0.3 ms&lt;/td&gt;
          &lt;td&gt;1.0x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;pdflatex&lt;/td&gt;
          &lt;td&gt;712 ms&lt;/td&gt;
          &lt;td&gt;1.4 ms&lt;/td&gt;
          &lt;td&gt;4.5x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Apache FOP&lt;/td&gt;
          &lt;td&gt;1.6 s&lt;/td&gt;
          &lt;td&gt;3.2 ms&lt;/td&gt;
          &lt;td&gt;10x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;LuaLaTeX&lt;/td&gt;
          &lt;td&gt;2.4 s&lt;/td&gt;
          &lt;td&gt;4.7 ms&lt;/td&gt;
          &lt;td&gt;15x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;sp&lt;/td&gt;
          &lt;td&gt;4.4 s&lt;/td&gt;
          &lt;td&gt;8.7 ms&lt;/td&gt;
          &lt;td&gt;28x&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;WeasyPrint&lt;/td&gt;
          &lt;td&gt;8.7 s&lt;/td&gt;
          &lt;td&gt;17.3 ms&lt;/td&gt;
          &lt;td&gt;55x&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;OK so this is where it gets interesting. Typst does 500 pages in 157 milliseconds. That is not a typo. Once it is running, it spends about 0.3ms per page. sp, which was basically equal at one page, needs 4.4 seconds — 28 times slower.&lt;/p&gt;
&lt;p&gt;At one page they are tied, at 500 pages it is not even close. Typst has maybe 60ms startup cost, and after that it just flies. The per-page cost of sp is roughly 28 times higher.&lt;/p&gt;
&lt;p&gt;Also worth noting: WeasyPrint really does not scale well. It goes from &amp;ldquo;ok&amp;rdquo; at one page to &amp;ldquo;maybe go get a coffee&amp;rdquo; at 500. pdflatex on the other hand scales surprisingly well — the per-page cost is only about 0.8ms if you subtract the startup.&lt;/p&gt;
&lt;p&gt;So if speed is all you care about, just use Typst, right?&lt;/p&gt;
&lt;h2 id=&#34;but-look-at-the-actual-output&#34;&gt;But look at the actual output&lt;/h2&gt;
&lt;p&gt;This is where it gets more complicated. Open the PDFs next to each other and look at the body text:&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2026/02/10/typesetting-benchmark/fourtexts.png&#34;  /&gt;
        
    
    
&lt;/figure&gt;


&lt;p&gt;You see the difference? The justified text looks different. Not because of different fonts — the &lt;em&gt;decisions&lt;/em&gt; are different. Where to break the lines, where to hyphenate, how to distribute the whitespace.&lt;/p&gt;
&lt;p&gt;pdflatex and sp use algorithms based on Knuth &amp;amp; Plass (the TeX line breaking algorithm). They look at the whole paragraph at once and find the best set of breakpoints for all lines together. The result is even word spacing, no rivers of white, and good hyphenation.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;Typst&lt;/del&gt;, WeasyPrint, and FOP seemingly use a much simpler algorithm. It looks like they go line by line from top to bottom and decide for each line separately. This is faster — and that is probably part of the reason why Typst scales so well. But you can see it. Some lines are too loose, some too tight. Hyphenation sometimes feels a bit random.
&lt;strong&gt;Edit&lt;/strong&gt; Typst&amp;rsquo;s author &lt;a href=&#34;https://mastodon.social/@typst/116048436705560152#.&#34;&gt;has clarified&lt;/a&gt;:  “However, one thing we noticed is your assertion in the justification section that Typst is not using Knuth-Plass – we do, by default when justification is enabled. The only thing of the original paper we don&amp;rsquo;t implement are tightness classes to prevent a very tight line and a very wide line directly next to each other.”&lt;/p&gt;
&lt;p&gt;For a simple letter, honestly both are fine. But try a narrow column with a technical text full of long words, and then you really see the difference. The Knuth-Plass output looks like a properly typeset book. The first-fit output looks like a web page that somebody printed.&lt;/p&gt;
&lt;p&gt;A benchmark cannot capture this.&lt;/p&gt;
&lt;h2 id=&#34;what-benchmarks-cannot-measure&#34;&gt;What benchmarks cannot measure&lt;/h2&gt;
&lt;p&gt;Here is what actually matters in production, and it has nothing to do with milliseconds: what happens when the content does not fit?&lt;/p&gt;
&lt;p&gt;Think of a product catalog. Each product gets one page: a data table at the top, product photos at the bottom. Simple enough. But then product number 47 has a table with 30 rows instead of 10. Now what?&lt;/p&gt;
&lt;p&gt;In Typst, you can use &lt;code&gt;measure()&lt;/code&gt; to get the height of the table and compare it with the available space. That is a reasonable approximation. But Typst cannot do a real trial layout across page breaks — it measures content in a single frame only.&lt;/p&gt;
&lt;p&gt;In the speedata Publisher, you can do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;SavePages&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attempt&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;PlaceObject&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;Table&amp;gt;&lt;/span&gt;...&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/PlaceObject&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/SavePages&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;Switch&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Case&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;test=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;sd:number-of-pages(&amp;#39;attempt&amp;#39;) &amp;gt; 2&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- does not fit — shrink font, split differently, whatever --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Case&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Otherwise&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;InsertPages&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attempt&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Otherwise&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Switch&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is real trial typesetting. It actually lays out the full content, with real page breaks, counts how many pages it needs, and then you decide: keep it, or throw it away and try with different settings. No other tool in this benchmark can do that.&lt;/p&gt;
&lt;p&gt;Is this slower than just going through the content without looking back? Of course. And maybe that is part of why sp is 28 times slower at 500 pages — it is built for &lt;em&gt;careful&lt;/em&gt; layout, not for &lt;em&gt;fast&lt;/em&gt; layout. But the alternative is that a human opens each PDF and manually checks if page 47 looks right. That is not a millisecond problem, that is a &amp;ldquo;you need to hire someone&amp;rdquo; problem.&lt;/p&gt;
&lt;h2 id=&#34;a-real-world-example-the-product-catalog-page&#34;&gt;A real-world example: the product catalog page&lt;/h2&gt;
&lt;p&gt;Here is an actual page from a spare parts catalog, built with the speedata Publisher. This is a very typical use case for a product catalog.&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2026/02/10/typesetting-benchmark/adaptivelayout.png&#34;  /&gt;
        
    
    
&lt;/figure&gt;


&lt;p&gt;Look at what is happening on this page. The data table grows from top to bottom — model by model, row by row. The product images at the bottom grow from bottom to top, in rows of up to four. The table and the images share the same page, and neither is allowed to overlap the other. The number of table rows varies per page, the number of product images varies per page, and the layout has to figure out on its own how to divide the available space.&lt;/p&gt;
&lt;p&gt;This is not a fixed template. It is an adaptive layout. The engine places the table, measures how much room is left, and fills the remaining space with as many product images as will fit — bottom-aligned, in rows of four. If a page has fewer products, you get two images in the last row instead of four. If the table is longer, the images get pushed to the next page. All of this happens automatically, without a human touching any page.&lt;/p&gt;
&lt;p&gt;How would you do this with the other tools?&lt;/p&gt;
&lt;p&gt;In Typst, you could get close. You would &lt;code&gt;measure()&lt;/code&gt; the table height, calculate the remaining space, and manually arrange images in a grid at the bottom. But you are doing layout math by hand, and if the table happens to break across pages, things get complicated fast. Typst has no built-in way to say &amp;ldquo;fill the rest of this page from the bottom up.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;In pdflatex or LuaLaTeX, you enter the world of TeX float placement — &lt;code&gt;\vfill&lt;/code&gt;, &lt;code&gt;\bottomrule&lt;/code&gt;, maybe a &lt;code&gt;minipage&lt;/code&gt; at the bottom. For a single page with a known table height, you could hack something together. But for hundreds of pages where the table height varies? You would likely write a Lua callback in LuaLaTeX that inspects the page after layout and inserts the images. Possible, but painful.&lt;/p&gt;
&lt;p&gt;In WeasyPrint, this is essentially not possible. CSS has no concept of &amp;ldquo;fill the remaining page from the bottom.&amp;rdquo; You would have to pre-calculate the table height outside of the rendering engine and generate custom CSS per page. At that point, you are not really using a layout engine anymore — you are the layout engine.&lt;/p&gt;
&lt;p&gt;In Apache FOP, XSL-FO has some support for this kind of thing with &lt;code&gt;region-after&lt;/code&gt; and &lt;code&gt;fo:block-container&lt;/code&gt;, but in practice FOP&amp;rsquo;s implementation is limited. You might get a rough approximation, but the automatic &amp;ldquo;grow from bottom&amp;rdquo; behavior is not something FOP handles well.&lt;/p&gt;
&lt;p&gt;In the speedata Publisher, this is roughly a dozen lines of layout XML. Place the table, ask how much space is left, arrange the images in the remaining area. It is exactly the kind of problem the tool was built for.&lt;/p&gt;
&lt;h2 id=&#34;the-difficulty-ladder&#34;&gt;The difficulty ladder&lt;/h2&gt;
&lt;p&gt;The real comparison is not &amp;ldquo;which tool is the fastest at a trivial task.&amp;rdquo; It is &amp;ldquo;which tool can even handle the task.&amp;rdquo;&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Task&lt;/th&gt;
          &lt;th&gt;Typst&lt;/th&gt;
          &lt;th&gt;sp&lt;/th&gt;
          &lt;th&gt;WeasyPrint&lt;/th&gt;
          &lt;th&gt;FOP&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Simple mail merge&lt;/td&gt;
          &lt;td&gt;fast&lt;/td&gt;
          &lt;td&gt;fast&lt;/td&gt;
          &lt;td&gt;medium&lt;/td&gt;
          &lt;td&gt;slow&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Justified text quality&lt;/td&gt;
          &lt;td&gt;ok&lt;/td&gt;
          &lt;td&gt;excellent&lt;/td&gt;
          &lt;td&gt;ok&lt;/td&gt;
          &lt;td&gt;ok&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&amp;ldquo;Does this fit on 2 pages?&amp;rdquo;&lt;/td&gt;
          &lt;td&gt;approximate&lt;/td&gt;
          &lt;td&gt;exact&lt;/td&gt;
          &lt;td&gt;no&lt;/td&gt;
          &lt;td&gt;no&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Dynamic layout fallbacks&lt;/td&gt;
          &lt;td&gt;manual&lt;/td&gt;
          &lt;td&gt;built-in&lt;/td&gt;
          &lt;td&gt;no&lt;/td&gt;
          &lt;td&gt;limited&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;200-page product catalog with conditional layouts&lt;/td&gt;
          &lt;td&gt;in theory&lt;/td&gt;
          &lt;td&gt;core use case&lt;/td&gt;
          &lt;td&gt;no&lt;/td&gt;
          &lt;td&gt;sort of&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a mail merge, use Typst. Seriously. It is fast, the source files are nice to write, and the output looks good enough.&lt;/p&gt;
&lt;p&gt;But once your layout needs go beyond &amp;ldquo;fill in a template, output PDF&amp;rdquo; — once you need the software to actually make &lt;em&gt;decisions&lt;/em&gt; — things change. And that is where tools like sp become worth it, even if they need a few hundred milliseconds more per page.&lt;/p&gt;
&lt;h2 id=&#34;what-i-actually-learned&#34;&gt;What I actually learned&lt;/h2&gt;
&lt;p&gt;I went into this benchmark hoping that sp would be fastest at everything. It is not. Typst is 28 times faster at 500 pages, and I cannot really argue with that — they have done amazing engineering work.&lt;/p&gt;
&lt;p&gt;But I also realized that the benchmark I set up — a simple mail merge — is exactly the kind of task where the strengths of sp do not show up at all. It is like you compare a sports car and a pickup truck on a flat highway. Sure, the sports car is faster. But that is not what you bought the truck for.&lt;/p&gt;
&lt;p&gt;The right question is not &amp;ldquo;how many pages per second.&amp;rdquo; It is &amp;ldquo;how many pages until you need a human to check.&amp;rdquo; And that is much harder to measure.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;The complete benchmark setup (all templates, scripts, and data) is on &lt;a href=&#34;https://github.com/speedata/typesetting-benchmark&#34;&gt;GitHub&lt;/a&gt;. Run &lt;code&gt;./benchmark.sh&lt;/code&gt; to reproduce on your own machine.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Fixing macOS notarization issues in the speedata Publisher 5.2.0</title>
      <link>https://news.speedata.de/2025/11/24/macossigningerror/</link>
      <pubDate>Mon, 24 Nov 2025 10:10:32 +0100</pubDate>
      
      <guid>https://news.speedata.de/2025/11/24/macossigningerror/</guid>
      <description>&lt;p&gt;I have rebuilt the macOS packages of the speedata Publisher and released them as version 5.2.1.
The Windows and Linux packages remain at 5.2.0, because the changes are macOS-specific.&lt;/p&gt;
&lt;p&gt;This post is a short write-up of what broke, how I debugged it, and which tools I used along the way. If you ever need to get a macOS command line tool notarized, this might save you some time (or at least a bit of frustration).&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-initial-problem&#34;&gt;The initial problem&lt;/h2&gt;
&lt;p&gt;The first hint that something was wrong came from a helpful macOS error message: the &lt;code&gt;sp&lt;/code&gt; binary from the downloaded ZIP refused to run and macOS complained about signature / security issues.&lt;/p&gt;
&lt;p&gt;At first glance, everything looked fine:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codesign -dv --verbose&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; bin/sp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;showed a valid Developer ID Application signature with hardened runtime, the correct team identifier, and a recent timestamp. So far, so good.&lt;/p&gt;
&lt;p&gt;However, Gatekeeper (the actual decision-maker on whether something is allowed to run) disagreed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;spctl -a -vvv bin/sp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;returned:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bin/sp: rejected
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;source=Unnotarized Developer ID
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;origin=Developer ID Application: PATRICK GUENTER GUNDLACH (3Y98DLKYBJ)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In other words:
“Nice signature, but this binary (or rather the package it lives in) is not notarized. Rejected.”&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-usual-suspects-quarantine-signature-notarization&#34;&gt;The usual suspects: quarantine, signature, notarization&lt;/h2&gt;
&lt;p&gt;There are a few common reasons why macOS complains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The file still has the quarantine attribute from the browser download:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;xattr bin/sp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;xattr -d com.apple.quarantine bin/sp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The binary is unsigned or only ad-hoc signed.&lt;/li&gt;
&lt;li&gt;The binary is signed, but the archive is not notarized.&lt;/li&gt;
&lt;li&gt;The wrong artifact was notarized (e.g. a different build or a different ZIP).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my case, the binary itself was correctly signed. The problem appeared at the notarization step.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;looking-at-the-notarization-log&#34;&gt;Looking at the notarization log&lt;/h2&gt;
&lt;p&gt;The key tool here is Apple’s notarization service and its logs.&lt;/p&gt;
&lt;p&gt;I submitted my ZIP for notarization using:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;xcrun notarytool submit speedata-publisher-macos-arm64-5.2.0.zip &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --apple-id &lt;span class=&#34;s2&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --team-id 3Y98DLKYBJ &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --keychain-profile &lt;span class=&#34;s2&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --wait
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The result:
&lt;code&gt;status: Invalid&lt;/code&gt; – the archive contained “critical validation errors”.&lt;/p&gt;
&lt;p&gt;The interesting part is in the JSON log, which looks roughly like this (simplified):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Invalid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;statusSummary&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Archive contains critical validation errors&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;issues&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;severity&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;speedata-publisher-macos-arm64-5.2.0.zip/.../jline-2.14.6.jar/META-INF/native/osx/libjansi.jnilib&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;The binary is not signed.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;architecture&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x86_64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is where the real debugging starts.&lt;/p&gt;
&lt;p&gt;The important insight:
Apple doesn’t just inspect your main executable (&lt;code&gt;bin/sp&lt;/code&gt;), it walks through the whole archive and looks at every Mach-O binary it can find:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.dylib&lt;/code&gt;, &lt;code&gt;.so&lt;/code&gt;, &lt;code&gt;.jnilib&lt;/code&gt;, helper executables, and so on&lt;/li&gt;
&lt;li&gt;even native libraries inside JAR files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If any of those are unsigned or signed incorrectly, notarization fails.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-unexpected-culprit-jline-2146jar&#34;&gt;The unexpected culprit: &lt;code&gt;jline-2.14.6.jar&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;One of the problematic paths stood out:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.../jline-2.14.6.jar/META-INF/native/osx/libjansi.jnilib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a native library (&lt;code&gt;libjansi.jnilib&lt;/code&gt;) embedded inside the JLine 2 JAR, originally used by Saxon for its interactive “Gizmo” tool. It contained old macOS code and was not signed at all.&lt;/p&gt;
&lt;p&gt;For the Publisher, I don’t actually need this library:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Publisher uses Saxon for XML/XSLT processing.&lt;/li&gt;
&lt;li&gt;The interactive JLine-based console is not part of the normal Publisher workflow.&lt;/li&gt;
&lt;li&gt;Shipping that native library is therefore unnecessary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once I realized that, the simplest solution was: remove JLine from the macOS package.&lt;/p&gt;
&lt;p&gt;That avoids the need to sign &lt;code&gt;libjansi.jnilib&lt;/code&gt; at all, and it removes old native code that is irrelevant on modern macOS systems (especially on arm64).&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;making-sure-the-remaining-binaries-are-signed&#34;&gt;Making sure the remaining binaries are signed&lt;/h2&gt;
&lt;p&gt;The notarization log also showed which other binaries Apple considers interesting in the archive, for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.../bin/sp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.../bin/sdluatex&lt;/code&gt; (a universal binary in my case)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.../share/lib/libsplib.so&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.../share/lib/luaglue.so&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these need a proper Developer ID Application signature.&lt;/p&gt;
&lt;p&gt;Instead of manually calling &lt;code&gt;codesign&lt;/code&gt; on every single file, I use &lt;a href=&#34;https://github.com/mitchellh/gon&#34;&gt;gon&lt;/a&gt; to automate this. Gon lets you define a configuration file that lists:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which binaries to sign&lt;/li&gt;
&lt;li&gt;which certificate to use&lt;/li&gt;
&lt;li&gt;and how to submit the final ZIP for notarization&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the process for a macOS release looks like this now:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build the binaries and shared libraries.&lt;/li&gt;
&lt;li&gt;Run gon with my configuration:
&lt;ul&gt;
&lt;li&gt;it calls &lt;code&gt;codesign&lt;/code&gt; with hardened runtime and timestamp&lt;/li&gt;
&lt;li&gt;it signs all relevant Mach-O binaries&lt;/li&gt;
&lt;li&gt;it submits the ZIP to Apple for notarization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Wait for the notarization result from &lt;code&gt;notarytool&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After removing JLine and letting gon sign all the relevant binaries, I rebuilt the ZIP and resubmitted it to Apple.&lt;/p&gt;
&lt;p&gt;This time the log looked much nicer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accepted&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;statusSummary&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Ready for distribution&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;ticketContents&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;speedata-publisher-macos-arm64-5.2.1.zip/.../bin/sp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;speedata-publisher-macos-arm64-5.2.1.zip/.../bin/sdluatex&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x86_64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;speedata-publisher-macos-arm64-5.2.1.zip/.../bin/sdluatex&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;speedata-publisher-macos-arm64-5.2.1.zip/.../share/lib/libsplib.so&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;speedata-publisher-macos-arm64-5.2.1.zip/.../share/lib/luaglue.so&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;“Accepted / Ready for distribution” is exactly what you want to see.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;final-check-with-gatekeeper&#34;&gt;Final check with Gatekeeper&lt;/h2&gt;
&lt;p&gt;After downloading and unpacking the ZIP on a fresh system, the final sanity check is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;spctl -a -vvv speedata-publisher/bin/sp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the result is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;speedata-publisher/bin/sp: accepted
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;source=Notarized Developer ID
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;origin=Developer ID Application: PATRICK GUENTER GUNDLACH (3Y98DLKYBJ)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At that point, macOS is happy and the package is ready to be used without scary warnings.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;For macOS users of the speedata Publisher:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The macOS package is now 5.2.1 and properly notarized.&lt;/li&gt;
&lt;li&gt;Windows and Linux stay at 5.2.0 for this release.&lt;/li&gt;
&lt;li&gt;The changes are purely about:
&lt;ul&gt;
&lt;li&gt;removing an unnecessary native library (JLine / &lt;code&gt;libjansi.jnilib&lt;/code&gt;), and&lt;/li&gt;
&lt;li&gt;making sure all relevant Mach-O binaries are correctly signed and notarized.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For anyone fighting similar issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;codesign -dv --verbose=4&lt;/code&gt; helps you inspect signatures.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spctl -a -vvv&lt;/code&gt; tells you what Gatekeeper thinks.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xcrun notarytool submit ... --wait&lt;/code&gt; plus the JSON log tell you exactly which file is causing notarization to fail.&lt;/li&gt;
&lt;li&gt;Using a tool like &lt;strong&gt;gon&lt;/strong&gt; makes it much easier to consistently sign and notarize all the right files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And sometimes the best fix is not to sign more, but to ship less.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Version 5.2 released</title>
      <link>https://news.speedata.de/2025/10/14/version-5_2_released/</link>
      <pubDate>Tue, 14 Oct 2025 14:41:48 +0200</pubDate>
      
      <guid>https://news.speedata.de/2025/10/14/version-5_2_released/</guid>
      <description>&lt;h1 id=&#34;big-improvements-under-the-hood&#34;&gt;Big Improvements Under the Hood&lt;/h1&gt;
&lt;p&gt;We’re happy to announce a new development snapshot of the &lt;em&gt;speedata Publisher&lt;/em&gt;!
This release comes with major internal improvements, cleaner architecture, and a bunch of small but meaningful user-facing enhancements.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;rewritten-xml-parser&#34;&gt;Rewritten XML Parser&lt;/h2&gt;
&lt;p&gt;The XML parser has been completely reimplemented in Go, with a stronger focus on &lt;strong&gt;correctness&lt;/strong&gt;, &lt;strong&gt;performance&lt;/strong&gt;, and &lt;strong&gt;test coverage&lt;/strong&gt;.
It now keeps track of the originating file when using &lt;strong&gt;XInclude&lt;/strong&gt;, which makes debugging and error reporting much easier.&lt;/p&gt;
&lt;p&gt;We’ve also added a comprehensive set of automated tests to ensure the parser behaves consistently across all edge cases.
This rewrite lays the foundation for future extensions such as XML entity support and better error recovery.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;smarter-xpath-engine&#34;&gt;Smarter XPath Engine&lt;/h2&gt;
&lt;p&gt;XPath support has grown significantly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New functions: &lt;code&gt;translate()&lt;/code&gt; and &lt;code&gt;distinct-values()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Improved numeric functions like &lt;code&gt;format-number()&lt;/code&gt; and &lt;code&gt;round-half-to-even()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;doc()&lt;/code&gt; function now returns the &lt;strong&gt;document node&lt;/strong&gt;, aligning better with the XPath standard&lt;/li&gt;
&lt;li&gt;More consistent boolean logic across the board&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means fewer surprises and more predictable results when working with complex expressions.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;typographic-and-language-support&#34;&gt;Typographic and Language Support&lt;/h2&gt;
&lt;p&gt;We’ve added &lt;strong&gt;initial Japanese typesetting support&lt;/strong&gt;, refined character fallback logic, and improved handling of multi-character glyphs.
These changes improve the Publisher’s internationalization capabilities and text layout quality — especially for multilingual projects.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;better-html-and-css-handling&#34;&gt;Better HTML and CSS Handling&lt;/h2&gt;
&lt;p&gt;The internal HTML/CSS engine continues to evolve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for pseudo-class selectors (like &lt;code&gt;:first-child&lt;/code&gt;, &lt;code&gt;:last-child&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Improved border and padding calculations in tables and blocks&lt;/li&gt;
&lt;li&gt;&lt;code&gt;list-style-position: inside|outside&lt;/code&gt; now supported&lt;/li&gt;
&lt;li&gt;&lt;code&gt;font-family&lt;/code&gt; accepts multiple fallback fonts&lt;/li&gt;
&lt;li&gt;Better behavior with custom &lt;code&gt;@font-face&lt;/code&gt; and relative font sizes (&lt;code&gt;rem&lt;/code&gt;, &lt;code&gt;px&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These refinements bring the output closer to what designers expect from modern HTML/CSS rendering.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;polished-pdf-output&#34;&gt;Polished PDF Output&lt;/h2&gt;
&lt;p&gt;PDF metadata has been updated to use ISO-formatted dates, and new metadata fields such as &lt;em&gt;Producer&lt;/em&gt; and default color profiles have been added automatically.
These subtle improvements help ensure better interoperability with other PDF tools and workflows.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;reliability-logging--maintenance&#34;&gt;Reliability, Logging &amp;amp; Maintenance&lt;/h2&gt;
&lt;p&gt;You’ll notice better diagnostic information throughout:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More descriptive log messages&lt;/li&gt;
&lt;li&gt;Multi-run jobs now continue even when earlier runs fail (useful for large builds)&lt;/li&gt;
&lt;li&gt;Safer handling of file attachments and image conversions&lt;/li&gt;
&lt;li&gt;Additional debugging details for developers and power users&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Under the hood, we also performed many small cleanups and documentation improvements to make the Publisher more maintainable in the long run.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What’s Next&lt;/h2&gt;
&lt;p&gt;We’re already working on the next big milestones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rewrite of the dynamic Go runtime library in Rust&lt;/strong&gt; — this will remove the last remaining &lt;code&gt;cgo&lt;/code&gt; dependency, improving performance and portability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;More unit testing and refactoring&lt;/strong&gt; to keep the core stable and future-proof.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed improvements&lt;/strong&gt; across XML, XPath, and rendering.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extended HTML/CSS support&lt;/strong&gt; for modern layout features.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;More XPath functions&lt;/strong&gt; to make data processing even more powerful.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;thank-you&#34;&gt;Thank You&lt;/h2&gt;
&lt;p&gt;A big thanks to everyone using and testing the speedata Publisher!
Your feedback and real-world examples help guide our development and make the tool better every day.&lt;/p&gt;
&lt;p&gt;If you’d like to follow ongoing work, check out the &lt;a href=&#34;https://github.com/speedata/publisher&#34;&gt;GitHub repository&lt;/a&gt; — and as always, happy publishing!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>billingcat – invoicing software powered by the speedata Publisher</title>
      <link>https://news.speedata.de/2025/10/07/billingcat/</link>
      <pubDate>Tue, 07 Oct 2025 13:17:04 +0200</pubDate>
      
      <guid>https://news.speedata.de/2025/10/07/billingcat/</guid>
      <description>&lt;p&gt;It has been a while since my last post on this blog.
This time I would like to introduce a project that is a bit different in scope but technically closely related to the speedata Publisher:
billingcat – an open-source application for invoicing and simple customer relationship management.&lt;/p&gt;
&lt;h2 id=&#34;what-is-billingcat&#34;&gt;What is billingcat?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://billingcat.de&#34;&gt;billingcat&lt;/a&gt; is an open-source project that combines two essential tasks for freelancers and small businesses:
creating invoices (including ZUGFeRD support) and managing customer data in a lightweight CRM.&lt;/p&gt;
&lt;p&gt;The project is currently in the alpha stage and only available in German, but already allows users to create invoices, manage clients, and use their own letterheads for invoices.&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2025/10/07/billingcat/dashboard.png&#34;  /&gt;
        
    
    
    &lt;div class=&#34;caption&#34;&gt;
        &lt;p&gt;Screenshot billingcat dashboard&lt;/p&gt;
        
    &lt;/div&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;connection-to-the-speedata-publisher&#34;&gt;Connection to the speedata Publisher&lt;/h2&gt;
&lt;p&gt;Under the hood, billingcat uses the speedata Publisher to generate ZUGFeRD-compliant PDF/A invoices.
The Publisher handles the PDF generation, embedding of XML data, and layout rendering.&lt;/p&gt;
&lt;p&gt;In the future, billingcat will also use the Publisher for other PDF outputs to take full advantage of its layout and automation features while keeping a simple web-based interface for end users.&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2025/10/07/billingcat/screenshot-standard-invoice.png&#34;  /&gt;
        
    
    
    &lt;div class=&#34;caption&#34;&gt;
        &lt;p&gt;Screenshot example invoice&lt;/p&gt;
        
    &lt;/div&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;looking-ahead&#34;&gt;Looking ahead&lt;/h2&gt;
&lt;p&gt;billingcat is still in its early stages, but the feedback from the first alpha testers has already been very encouraging.
For me, this project is also a great example of how the speedata Publisher can be integrated into other systems to produce high-quality document output – even as part of modern web applications.&lt;/p&gt;
&lt;p&gt;In an upcoming post, I plan to write about a brand-new feature in billingcat: the Letterhead Editor.
It allows users to design their own letterheads and upload custom font files, making it possible to generate personalized layouts without additional coding effort.&lt;/p&gt;
&lt;p&gt;More on that soon here on the blog.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;More information about the project: &lt;a href=&#34;https://billingcat.de&#34;&gt;billingcat.de&lt;/a&gt;&lt;br&gt;
Source code on GitHub: &lt;a href=&#34;https://github.com/billingcat&#34;&gt;github.com/billingcat&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>High speed PDF generation with boxes and glue</title>
      <link>https://news.speedata.de/2025/05/27/highspeedpdfgeneration/</link>
      <pubDate>Tue, 27 May 2025 08:28:23 +0200</pubDate>
      
      <guid>https://news.speedata.de/2025/05/27/highspeedpdfgeneration/</guid>
      <description>&lt;p&gt;This article is not up to date anymore, I will leave it online. Risor is not supported anymore Lua is now the choice of scripting language. I will post a follow-up soon.&lt;/p&gt;
&lt;p&gt;I have been playing with electronic invoices (especially the German and French &lt;a href=&#34;https://www.ferd-net.de/en/&#34;&gt;ZUGFeRD/Factur-X&lt;/a&gt; format) for a while now. The &lt;a href=&#34;https://www.speedata.de/de/&#34;&gt;speedata Publisher&lt;/a&gt; has support for ZUGFeRD since 2017.&lt;/p&gt;
&lt;p&gt;The next step is to make (my other PDF generation software) &lt;a href=&#34;https://boxesandglue.dev&#34;&gt;boxes and glue&lt;/a&gt; work with electronic invoices. For that, I use the new &lt;a href=&#34;https://github.com/boxesandglue/cli&#34;&gt;command line interface&lt;/a&gt; for boxes and glue (which I will describe in a future blog post).&lt;/p&gt;
&lt;p&gt;There only a few things that need to be done to make this work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need an XML file that contains the invoice data. This is usually generated by an accounting software. This must be conformant to the ZUGFeRD XML schema (EN 16931-1).&lt;/li&gt;
&lt;li&gt;Attach the XML to the generated PDF.&lt;/li&gt;
&lt;li&gt;Create a visual representation of the invoice data in the PDF.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is an example of the script at &lt;a href=&#34;https://github.com/boxesandglue/boxesandglue-examples/tree/main/commandline/zugferdinvoice&#34;&gt;GitHub&lt;/a&gt;. Get the software as described on &lt;a href=&#34;https://github.com/boxesandglue/cli&#34;&gt;https://github.com/boxesandglue/cli&lt;/a&gt; and run&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bag main.rsr
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which generates a file &lt;code&gt;out0.pdf&lt;/code&gt; from the sample &lt;code&gt;zugferd.xml&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;The console output is something like&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Define font family (name=text,id=0)
Load image (filename=img/logo.pdf)
Load font (filename=../../fonts/crimsonpro/CrimsonPro-Regular.ttf)
Load font (filename=../../fonts/crimsonpro/CrimsonPro-Bold.ttf)
Add attachment (filename=factur-x.xml)
Write image to PDF (filename=img/logo.pdf)
Write font to PDF (filename=../../fonts/crimsonpro/CrimsonPro-Regular.ttf,psname=CrimsonPro-Regular)
Write font to PDF (filename=../../fonts/crimsonpro/CrimsonPro-Bold.ttf,psname=CrimsonPro-Bold)
Output written (filename=out0.pdf,bytes=28073)
finished in 26.91ms
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;27 milliseconds (on my 2021 MacBook Pro) for a PDF is not bad, I guess.
This includes loading fonts and the PDF logo, parsing the XML file and writing the PDF, subsetting and including fonts and attaching the XML file.&lt;/p&gt;
&lt;p&gt;The 27 milliseconds include some startup time, so let me check what happens when I run the script 1000 times (set maxdocuments in the script to 1000):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
finished in 14224.74ms
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is about 14 milliseconds for one document or approximately 70 documents per second.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Version 5 Released</title>
      <link>https://news.speedata.de/2025/03/12/version-5-released/</link>
      <pubDate>Wed, 12 Mar 2025 14:43:15 +0100</pubDate>
      
      <guid>https://news.speedata.de/2025/03/12/version-5-released/</guid>
      <description>&lt;p&gt;Almost five years after releasing version 4.0 of the &lt;a href=&#34;https://www.speedata.de/&#34;&gt;speedata Publisher&lt;/a&gt;, it is time for version 5.0. This is a short announcement, since most changes have been covered before.&lt;/p&gt;
&lt;p&gt;The speedata Publisher looks the same since its beginning, but there have been major changes under the hood since version 4:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integration of HarfBuzz for left to right and right to left text layout, even mixed (bidirectional) typesetting. Support for all kinds of fonts and font features.&lt;/li&gt;
&lt;li&gt;Full accessibility support.&lt;/li&gt;
&lt;li&gt;A rewritten XML and XPath 2.0 parser.&lt;/li&gt;
&lt;li&gt;Attachment of ZUGFeRD invoices.&lt;/li&gt;
&lt;li&gt;Greatly enhance enhance various subsystems such as HTML, MetaPost integration and paragraph builder.&lt;/li&gt;
&lt;li&gt;SAAS available with the speedata Pro plan.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There have been a few entries here in the blog (&lt;a href=&#34;https://news.speedata.de/2024/01/08/new_version_4_16/&#34;&gt;4.16&lt;/a&gt;, &lt;a href=&#34;https://news.speedata.de/2024/04/22/release-speedata-publisher-4-18/&#34;&gt;4.18&lt;/a&gt;, &lt;a href=&#34;https://news.speedata.de/2025/01/15/version-4-20-release/&#34;&gt;4.20&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Some statistics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are 246 black box tests to check that all existing layouts keep working as before. This is 132 more than in version 4.&lt;/li&gt;
&lt;li&gt;A bit more than 220 development releases and 10 stable releases between 4.0 and 5.0&lt;/li&gt;
&lt;li&gt;906 commits since 4.0&lt;/li&gt;
&lt;li&gt;Git stat tells me: 989 files changed, 66328 insertions, 18099 deletions&lt;/li&gt;
&lt;li&gt;More than 250 closed bug reports.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This would not be possible without all the bug reports and helpful comments from the users. So thank you very much!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>speedata Publisher and AI</title>
      <link>https://news.speedata.de/2025/02/04/speedatapublisherai/</link>
      <pubDate>Mon, 03 Feb 2025 20:58:20 +0100</pubDate>
      
      <guid>https://news.speedata.de/2025/02/04/speedatapublisherai/</guid>
      <description>&lt;p&gt;Don&amp;rsquo;t worry, the speedata Publisher will not gain any half-baked, annoying artificial intelligence features.
This post is about chatting with some of the more famous AI chats (ChatGPT, Google Gemini, DeepSeek).
I have tried to find out how good these AI chats know the speedata Publisher and if they can help users to generate a layout.&lt;/p&gt;
&lt;p&gt;There is still a long road ahead, but read on. A big &lt;strong&gt;warning&lt;/strong&gt; upfront: None the following outputs work. Do not use them. I post abbreviated transcripts of the chats.&lt;/p&gt;
&lt;p&gt;Table of contents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#chat-gpt&#34;&gt;Chat GPT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#google-gemini&#34;&gt;Google Gemini&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#deepseek&#34;&gt;DeepSeek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;chat-gpthttpschatgptcom&#34;&gt;&lt;a href=&#34;https://chatgpt.com&#34;&gt;Chat GPT&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;me&lt;/strong&gt;: Do you know the speedata Publisher?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; Yes! Speedata Publisher is an open-source automated publishing system designed for high-volume and complex document generation, especially for structured data like catalogs, financial reports, and technical documents. It uses XML and Lua to define document layouts and logic, making it highly customizable for professional publishing needs.&lt;/p&gt;
&lt;p&gt;It’s particularly useful when you need precise typography and layout control, similar to tools like TeX or InDesign scripting, but optimized for structured data.&lt;/p&gt;
&lt;p&gt;Are you considering using it for a project?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;me:&lt;/strong&gt; can you generate a simple layout for the speedata publisher just printing a &amp;ldquo;hello chatgpt&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; Sure! Here’s a simple Speedata Publisher layout file that prints &amp;ldquo;Hello ChatGPT&amp;rdquo; on a page. Save this as an XML file and run it with Speedata Publisher.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;document&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;xmlns=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;https://www.speedata.de/2012/publisher/en&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;setup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;pagelayout&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;mainlayout&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;positioningarea&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;width=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;210mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;height=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;297mm&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nt&#34;&gt;&amp;lt;text&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;top=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;50mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;left=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;50mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;fontsize=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;20pt&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    Hello ChatGPT
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nt&#34;&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;/positioningarea&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/pagelayout&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/setup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;record&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;page&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;usepagelayout&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;mainlayout&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/page&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Explanation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defines a page layout (mainlayout) of A4 size.&lt;/li&gt;
&lt;li&gt;Places &amp;ldquo;Hello ChatGPT&amp;rdquo; at 50mm from the top and left.&lt;/li&gt;
&lt;li&gt;Creates a record that generates a page using the defined layout.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Would you like to extend this with styles, different fonts, or dynamic content? 🚀&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;me:&lt;/strong&gt;
The speedata Publisher needs a data file, can you show it to me as well?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; You&amp;rsquo;re absolutely right! Speedata Publisher requires a data file along with the layout. Here’s a minimal data file to use with the previous layout:&lt;/p&gt;
&lt;p&gt;data.xml&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;text&amp;gt;&lt;/span&gt;Hello ChatGPT&lt;span class=&#34;nt&#34;&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Updated Layout File (layout.xml)&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s modify the layout to fetch data dynamically instead of hardcoding the text:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;document&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;xmlns=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;https://www.speedata.de/2012/publisher/en&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;setup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;pagelayout&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;mainlayout&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;positioningarea&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;width=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;210mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;height=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;297mm&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nt&#34;&gt;&amp;lt;text&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;top=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;50mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;left=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;50mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;fontsize=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;20pt&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;nt&#34;&gt;&amp;lt;value&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nt&#34;&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;/positioningarea&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/pagelayout&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/setup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;record&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;element=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;page&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;usepagelayout&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;mainlayout&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/page&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How it Works:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;data.xml contains the text inside a &lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt; element.&lt;/li&gt;
&lt;li&gt;The layout file dynamically fetches the text using &lt;code&gt;&amp;lt;value select=&amp;quot;text&amp;quot;/&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When you run Speedata Publisher with both files, it will output &amp;ldquo;Hello ChatGPT&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;!--
Would you like any modifications, such as custom fonts or multiple text elements? 😊

**me:** How do I start the speedata Publisher?

**ChatGPT:** To start Speedata Publisher, follow these steps:

1. Download &amp; Install Speedata Publisher
 *	Get it from the official site: https://www.speedata.de/en/publisher/download
 *	Extract or install it based on your OS (Windows, macOS, Linux).

2. Prepare Your Files

Make sure you have:
 *	layout.xml (your layout file)
 *	data.xml (your data file)

Both should be in the same folder.

3 Run Speedata Publisher

Open a terminal or command prompt and navigate to the folder where your files are stored. Then run:

```sh
speedata-publisher layout.xml
```

or if installed locally:

```sh
./speedata-publisher layout.xml
```
4 Check the Output

* By default, it generates a PDF file in the same folder.
* Open the generated PDF and verify the result.

--&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;google-geminihttpsgeminigooglecomapp&#34;&gt;&lt;a href=&#34;https://gemini.google.com/app&#34;&gt;Google Gemini&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;me:&lt;/strong&gt; do you know the speedata Publisher?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gemini:&lt;/strong&gt; Yes, I do!&lt;/p&gt;
&lt;p&gt;Speedata Publisher is a powerful and versatile typesetting software that&amp;rsquo;s particularly well-suited for creating complex documents with a high degree of automation. It&amp;rsquo;s known for its ability to handle large volumes of data and produce professional-quality output.  &lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what I know about Speedata Publisher:&lt;/p&gt;
&lt;p&gt;[&amp;hellip;]&lt;/p&gt;
&lt;!--
*	Focus on Automation: Speedata excels at automating the typesetting process. It can take data from various sources (like databases or XML files) and automatically generate documents like catalogs, reports, and brochures.  
*	Rule-Based Typesetting: It uses a rule-based approach, allowing you to define precise formatting rules that are applied consistently throughout your documents. This ensures a uniform look and feel, even with large amounts of data.  
*	XML-Based: Speedata works with XML as its primary input format, making it ideal for workflows that involve structured data.
*	Open Source: It&#39;s open-source software, which means it&#39;s free to use and modify. This also fosters a strong community around the software.  
*	Command-Line Interface: Speedata is primarily used through a command-line interface, giving you a lot of control and making it easy to integrate into automated workflows.  
Do you have any specific questions about Speedata Publisher that I can help you with? For example, I can try to answer questions about:
*	Its features and capabilities
*	How it compares to other typesetting software
*	Where to find documentation and support
*	Use cases and examples
--&gt;
&lt;p&gt;I&amp;rsquo;m ready to assist you further! Just let me know what you&amp;rsquo;d like to know.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;me:&lt;/strong&gt; can you generate a simple layout for the speedata publisher just printing a &amp;ldquo;hello gemini&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gemini:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;document&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;xmlns=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;http://speedata.org/2021/03/speedata&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;layout&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;page&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;lt;frame&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;x=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1cm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;y=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1cm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;width=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;10cm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;height=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;2cm&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;text&amp;gt;&lt;/span&gt;Hello Gemini&lt;span class=&#34;nt&#34;&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;lt;/frame&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/page&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/document&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Explanation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/code&gt;: Standard XML declaration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;document xmlns=&amp;quot;http://speedata.org/2021/03/speedata&amp;quot;&amp;gt;&lt;/code&gt;: The root element, declaring the Speedata namespace. This is crucial.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;layout&amp;gt;&lt;/code&gt;: Contains the layout definition.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;page&amp;gt;&lt;/code&gt;: Defines a single page. You can have multiple &lt;code&gt;&amp;lt;page&amp;gt;&lt;/code&gt; elements for multi-page documents.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;frame x=&amp;quot;1cm&amp;quot; y=&amp;quot;1cm&amp;quot; width=&amp;quot;10cm&amp;quot; height=&amp;quot;2cm&amp;quot;&amp;gt;&lt;/code&gt;: Defines a rectangular area on the page.
&lt;ul&gt;
&lt;li&gt;x and y attributes specify the top-left corner&amp;rsquo;s position (1cm from the left and 1cm from the top).&lt;/li&gt;
&lt;li&gt;width and height define the dimensions of the frame.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;text&amp;gt;Hello Gemini&amp;lt;/text&amp;gt;&lt;/code&gt;: The content to be printed within the frame.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How to use this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Save: Save this code as an XML file (e.g., hello.xml).&lt;/li&gt;
&lt;li&gt;Run Speedata: Open a terminal or command prompt and navigate to the directory where you saved the file. Then, run Speedata Publisher using the command: &lt;code&gt;speedata hello.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This will generate a PDF file (usually named hello.pdf) containing your &amp;ldquo;Hello Gemini&amp;rdquo; text.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Key improvements and considerations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Namespace: The xmlns attribute in the &lt;code&gt;&amp;lt;document&amp;gt;&lt;/code&gt; tag is essential for Speedata to understand the XML structure.&lt;/li&gt;
&lt;li&gt;Units: Using units like cm (centimeters) is good practice for defining sizes and positions. Speedata supports various units (mm, in, pt, etc.).&lt;/li&gt;
&lt;li&gt;Frame: The &lt;code&gt;&amp;lt;frame&amp;gt;&lt;/code&gt; element is important for positioning content precisely. Without it, the text might be placed at the default position.&lt;/li&gt;
&lt;li&gt;Error Handling: If you encounter errors, double-check the XML syntax and make sure Speedata is installed correctly. The command-line output will often provide clues about the problem.
This example provides a very basic layout. Speedata Publisher is capable of much more complex layouts with sophisticated formatting, data integration, and conditional rules. If you have more specific layout requirements, let me know, and I&amp;rsquo;ll do my best to help you create the appropriate Speedata code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;deepseekhttpswwwdeepseekcom&#34;&gt;&lt;a href=&#34;https://www.deepseek.com&#34;&gt;DeepSeek&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;me:&lt;/strong&gt; do you know the speedata publisher?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DeepSeek:&lt;/strong&gt; Yes, Speedata Publisher is a specialized software tool designed for automated typesetting and layout generation, particularly for complex documents like catalogs, directories, and price lists. It uses a data-driven approach, allowing users to define layouts through XML or JSON data and templates. This makes it highly efficient for handling large datasets and generating consistent, high-quality layouts.&lt;/p&gt;
&lt;p&gt;Key features of Speedata Publisher include:&lt;/p&gt;
&lt;p&gt;[&amp;hellip;]&lt;/p&gt;
&lt;!--
Data-Driven Layouts: It processes structured data (e.g., XML or JSON) to generate layouts, making it ideal for repetitive or data-heavy documents.
Automation: It automates the typesetting process, reducing manual effort and ensuring consistency across large documents.
Customizable Templates: Users can create templates to define the design and structure of the document.
PDF Output: It generates print-ready PDFs, suitable for professional publishing.
Open Source: Speedata Publisher is open-source, allowing users to modify and extend its functionality.
It’s particularly popular in industries like retail, e-commerce, and publishing, where managing large volumes of product data and generating catalogs or price lists is a common requirement. If you have specific questions about its usage or features, feel free to ask!
--&gt;
&lt;p&gt;&lt;strong&gt;me:&lt;/strong&gt; can you generate a simple layout for the speedata publisher just printing a &amp;ldquo;hello deepseek&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DeepSeek:&lt;/strong&gt; Certainly! Below is a simple example of how you can create a layout in Speedata Publisher to print &amp;ldquo;Hello Deepseek&amp;rdquo;. This example assumes you have a basic understanding of XML and how Speedata Publisher works.
Step 1: Create the Data File (data.xml)
This file contains the data you want to display in your layout.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;message&amp;gt;&lt;/span&gt;Hello Deepseek&lt;span class=&#34;nt&#34;&gt;&amp;lt;/message&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Step 2: Create the Layout File (layout.xml)
This file defines the layout and how the data should be displayed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;Layout&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;xmlns=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;urn:speedata.de:2009/publisher/en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;na&#34;&gt;xmlns:sd=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;urn:speedata:2009/publisher/functions/en&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- Define a page template --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;Pageformat&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;width=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;210mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;height=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;297mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- A4 size --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;DefinePage&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;width=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;210mm&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;height=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;297mm&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;PlaceObject&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;column=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;row=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;Textblock&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nt&#34;&gt;&amp;lt;Paragraph&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;nt&#34;&gt;&amp;lt;Value&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/data/message&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- Insert the message from the data file --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Paragraph&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Textblock&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/PlaceObject&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/DefinePage&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- Start the layout with the &amp;#34;main&amp;#34; page --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;Record&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;element=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;ClearPage&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;UsePage&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Record&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Layout&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Step 3: Run Speedata Publisher&lt;/p&gt;
&lt;p&gt;To generate the PDF, run the Speedata Publisher command with the data and layout files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sp data.xml layout.xml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will produce a PDF file with &amp;ldquo;Hello Deepseek&amp;rdquo; printed on an A4-sized page.
Explanation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;data.xml: Contains the message &amp;ldquo;Hello Deepseek&amp;rdquo; in a structured format.&lt;/li&gt;
&lt;li&gt;layout.xml: Defines the layout, including the page size (A4) and where the message should be placed (column 1, row 1).&lt;/li&gt;
&lt;li&gt;Speedata Command: The sp command processes the data and layout files to generate the PDF.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The correct answer would be something like this:&lt;/p&gt;
&lt;p&gt;The data.xml file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;data&amp;gt;&lt;/span&gt;Hello world!&lt;span class=&#34;nt&#34;&gt;&amp;lt;/data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and the layout file (layout.xml)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;Layout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;na&#34;&gt;xmlns=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;urn:speedata.de:2009/publisher/en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;na&#34;&gt;xmlns:sd=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;urn:speedata:2009/publisher/functions/en&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Record&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;element=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;PlaceObject&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;lt;Textblock&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;Paragraph&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;lt;Value&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Paragraph&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Textblock&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/PlaceObject&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/Record&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Layout&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and to run the speedata Publisher, just call &lt;code&gt;sp&lt;/code&gt;  on the command line.&lt;/p&gt;
&lt;p&gt;To be honest: all three chat AI gave really bad answers. The ChatGPT and the Gemini answers were totally useless, the DeepSeek AI gave a bit better answer, at least it outputs some commands that are actually part of the speedata Publisher layout language.&lt;/p&gt;
&lt;p&gt;I know that the speedata Publisher is a niche product where you cannot find many examples on the web. So it is hard for the limited AI data models to output anything useful. I was impressed by DeepSeek that it outputs at least a few sensible speedata Publisher commands. I should re-visit the chats in a few years and update this blog entry.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Electronic invoices</title>
      <link>https://news.speedata.de/2025/01/21/einvoicing/</link>
      <pubDate>Tue, 21 Jan 2025 11:34:52 +0100</pubDate>
      
      <guid>https://news.speedata.de/2025/01/21/einvoicing/</guid>
      <description>&lt;p&gt;&lt;em&gt;The following text is written from a German perspective. This should apply to all parts of the European Union, although with likely differences in other countries.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Since the beginning of 2025, all companies in Germany have had to send and receive electronic invoices (with overriding deadlines and a few exceptions). This affects me too, so I asked myself (out of curiosity), what is an electronic invoice and how can I process it?&lt;/p&gt;
&lt;h2 id=&#34;e-invoice&#34;&gt;E-invoice&lt;/h2&gt;
&lt;p&gt;An e-invoice is defined in the EN 16931 standard. This consists of several parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;the first part of the standard describes in general terms how an invoice must be structured. For example, a seller must be specified, the types of VAT are defined and the necessary and optional contents of an invoice are described. There is also a series of (business) rules that check the semantic validity of an invoice.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second part consists of an analysis of various existing XML standards with regard to compatibility with the first part of the standard. The result of this analysis is that there are two allowed XML standards: CII and UBL (which are two different standards but &lt;a href=&#34;https://groups.oasis-open.org/higherlogic/ws/public/document?document_id=57887&#34;&gt;have the same roots&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the third part describes an assignment of the invoice terms to the XML elements of the CII or UBL implementations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;zugferd-and-factur-x--cii&#34;&gt;ZUGFeRD and Factur-X / CII&lt;/h2&gt;
&lt;p&gt;The German &lt;a href=&#34;https://www.ferd-net.de&#34;&gt;ZUGFeRD&lt;/a&gt; and the French &lt;a href=&#34;https://fnfe-mpe.org&#34;&gt;Factur-X&lt;/a&gt; are identical standards that are based on CII (cross industry invoice). These are hybrid formats that have a human-readable and a machine-readable part, implemented as a PDF document with an XML attachment. The invoice visible in the PDF is also saved as XML in the attachment:&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2025/01/21/einvoicing/theyarethesamepicture@0.5x.png&#34;  /&gt;
        
    
    
&lt;/figure&gt;


&lt;h2 id=&#34;ubl&#34;&gt;UBL&lt;/h2&gt;
&lt;p&gt;UBL based invoices (&lt;a href=&#34;https://groups.oasis-open.org/communities/tc-community-home2?CommunityKey=556949c8-dac8-40e6-bb16-018dc7ce54d6&#34;&gt;Universal Busines Language&lt;/a&gt;, defined in ISO 19845 by OASIS) is a different approach to electronic invoicing. Many countries have ULB based invoices (or a subset of it), for example Denmark has OIOUBL, Norways EHF and you can find many more such examples.&lt;/p&gt;
&lt;p&gt;In Germany, UBL based invoices are popular in government agencies, not so much among b2b invoices.&lt;/p&gt;
&lt;h2 id=&#34;xrechnung&#34;&gt;XRechnung&lt;/h2&gt;
&lt;p&gt;There is yet another invoicing standard in Germany which might lead to confusion. The &lt;a href=&#34;https://en.e-rechnung-bund.de&#34;&gt;XRechnung standard&lt;/a&gt; is based on both ZUGFeRD CII and UBL format. It also defines some further business rules which are important for government agencies.&lt;/p&gt;
&lt;h2 id=&#34;peppol&#34;&gt;Peppol&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/PEPPOL&#34;&gt;Peppol (Pan-European Public Procurement OnLine)&lt;/a&gt; is a set of applications which includes electronic invoicing (based on the UBL standard). Many countries around the world implement the Peppol standard, see the &lt;a href=&#34;https://peppol.org/learn-more/country-profiles/&#34;&gt;country profiles list&lt;/a&gt; on &lt;a href=&#34;https://peppol.org&#34;&gt;peppol.org&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;other-countries&#34;&gt;Other Countries&lt;/h2&gt;
&lt;p&gt;There are several sites on the internet that show the standards for electronic invoicing regulations for a lot of countries around the world, for example the page at &lt;a href=&#34;https://edicomgroup.com/electronic-invoicing/&#34;&gt;edicomgroup.com/electronic-invoicing&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;zugferd-and-ubl-based-xml&#34;&gt;ZUGFeRD (and UBL based) XML&lt;/h2&gt;
&lt;p&gt;How does an XML for the ZUGFeRD/Factur-X format look like? This is described in detail in the documentation which can be downloaded from &lt;a href=&#34;https://www.ferd-net.de/download-zugferd&#34;&gt;ferd-net&lt;/a&gt;. ZUGFeRD comes in several “conformance levels” (profiles), the EN16931 level should be used for electronic invoices. There are some examples at &lt;a href=&#34;https://github.com/ZUGFeRD/corpus/tree/master/XML-Rechnung/CII&#34;&gt;https://github.com/ZUGFeRD/corpus/tree/master/XML-Rechnung/CII&lt;/a&gt;. See the other directories for UBL based invoices.&lt;/p&gt;
&lt;h2 id=&#34;attaching-an-electronic-invoice-to-a-pdf&#34;&gt;Attaching an electronic invoice to a PDF&lt;/h2&gt;
&lt;p&gt;The ZUGFeRD format is (as described) a PDF with an attached XML. The PDF must conform to the PDF/A-3 standard and also include some special metadata. Both are described in the ZUGFeRD documentation.&lt;/p&gt;
&lt;p&gt;Attaching a ZUGFeRD invoice with the speedata Publisher is very easy. Just call &lt;code&gt;&amp;lt;AttachFile&amp;gt;&lt;/code&gt;  with the type &lt;code&gt;ZUGFeRD invoice&lt;/code&gt; and the speedata Publisher does the rest automatically. See the&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;AttachFile&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;description=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Electronic invoice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;na&#34;&gt;type=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ZUGFeRD invoice&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;na&#34;&gt;filename=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;invoice.pdf&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;development&#34;&gt;Development&lt;/h2&gt;
&lt;p&gt;I have setup the site &lt;a href=&#34;https://erechnung.berlin&#34;&gt;erechnung.berlin&lt;/a&gt; (in German) mainly for my own purposes to &lt;a href=&#34;https://erechnung.berlin/check/&#34;&gt;check and visualize&lt;/a&gt; ZUGFeRD files and to show a hierarchical &lt;a href=&#34;https://erechnung.berlin/cii/&#34;&gt;list of all allowed XML elements&lt;/a&gt; and their cardinality. The checker uses &lt;a href=&#34;https://github.com/speedata/einvoice&#34;&gt;a Go library&lt;/a&gt; to read the XML file and is implemented as a WASM program, so it runs in the browser and does not transfer any data to a server.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The whole topic “e-invoices” looks complicated, but once the sender and the receiver have setup a process for these XML files, many new applications for automation can be developed. As a simple example, the banking account number and the due payable amount are stored in well known fields, so you might be able to drop an electronic invoice on the banking software which creates a money transfer template for you.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Release stable version 4.20</title>
      <link>https://news.speedata.de/2025/01/15/version-4-20-release/</link>
      <pubDate>Wed, 15 Jan 2025 13:00:01 +0100</pubDate>
      
      <guid>https://news.speedata.de/2025/01/15/version-4-20-release/</guid>
      <description>&lt;p&gt;After more than half a year, 150 commits and 40 minor releases, I have now published version 4.20, which is hopefully the last stable version before the “big five”.&lt;/p&gt;
&lt;p&gt;As always, old document should run without any changes.
You might have to switch on compatibility modes with &lt;code&gt;--xpath=lxpath&lt;/code&gt; and &lt;code&gt;--option fontloader=fontforge&lt;/code&gt; on the command line, but in most cases, the new defaults should not change your document output&lt;/p&gt;
&lt;p&gt;There are some major enhancements compared to the previous stable version (4.18):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fully accessible documents (PDF/UA)&lt;/li&gt;
&lt;li&gt;XPath parser now well tested and with more functionality&lt;/li&gt;
&lt;li&gt;ZUGFeRD attachment compatible with version 2.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And some minor enhancements&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Spot color saturation&lt;/li&gt;
&lt;li&gt;Ability to flip (mirror) objects&lt;/li&gt;
&lt;li&gt;Derived glyphs now copy-able in HarfBuzz mode&lt;/li&gt;
&lt;li&gt;PDF/A-3 selectable as an output format&lt;/li&gt;
&lt;li&gt;Font sizes and shift for superscript and subscript can be configured&lt;/li&gt;
&lt;li&gt;Inner and outer margins in Pagetype&lt;/li&gt;
&lt;li&gt;New strategy for NoBreak: reduce=fontfit&lt;/li&gt;
&lt;li&gt;Font expansion setting configurable&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;fully-accessible-documents-pdfua&#34;&gt;Fully accessible documents (PDF/UA)&lt;/h2&gt;
&lt;p&gt;You can now create accessible PDF documents in a fully automatic workflow.
You need to define the roles of each element (“this is a heading&amp;hellip;”) and take care of the correct order of the elements in the PDF. The PAC (PDF accessibility checker) is very happy with the PDFs that come out of the speedata Publisher. There is a &lt;a href=&#34;https://doc.speedata.de/publisher/en/advancedtopics/accessibility/&#34;&gt;whole section in the documentation&lt;/a&gt; dedicated to PDF/UA output.&lt;/p&gt;
&lt;h2 id=&#34;xpath-parser-lxpath&#34;&gt;XPath parser (lxpath)&lt;/h2&gt;
&lt;p&gt;The (not so) new (anymore) Lua XPath 2.0 parser has been thoroughly tested and is now recommended for all new projects. It can be set into a strict namespace mode which makes it easy to work with mixed namespace data.&lt;/p&gt;
&lt;p&gt;It also handles variables &lt;a href=&#34;https://github.com/speedata/publisher/discussions/612&#34;&gt;more consistent&lt;/a&gt; than before.&lt;/p&gt;
&lt;h2 id=&#34;zugferd-attachments&#34;&gt;ZUGFeRD attachments&lt;/h2&gt;
&lt;p&gt;ZUGFeRD (electronic invoices, also known as Factur-X in France) have got an overhaul. The file name of the attached file is now &lt;code&gt;factur-x.xml&lt;/code&gt; for version 2. The PDF/A-3 conformance has also improved by writing output intents for CMYK colors (configurable) and a few other minor improvements.&lt;/p&gt;
&lt;p&gt;You can download the version 4.20 as always at &lt;a href=&#34;https://download.speedata.de&#34;&gt;https://download.speedata.de&lt;/a&gt;. Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Creating PDF with JavaScript</title>
      <link>https://news.speedata.de/2024/10/14/pdfwithjavascript/</link>
      <pubDate>Mon, 14 Oct 2024 12:33:55 +0200</pubDate>
      
      <guid>https://news.speedata.de/2024/10/14/pdfwithjavascript/</guid>
      <description>&lt;p&gt;I have created JavaScript bindings for &lt;a href=&#34;https://boxesandglue.dev&#34;&gt;boxes and glue&lt;/a&gt;. These bindings are made with &lt;a href=&#34;https://github.com/dop251/goja&#34;&gt;goja&lt;/a&gt;. Let me show you an example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;bag&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;bag:backend/bag&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;bag:frontend&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;out.pdf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`In olden times when wishing still helped one,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;there lived a king whose daughters were all beautiful;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;and the youngest was so beautiful that the sun itself,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;which has seen so much, was astonished whenever it shone
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;in her face. Close by the king’s castle lay a great dark
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;forest, and under an old lime-tree in the forest was a well,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;and when the day was very warm, the king’s child went out
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;into the forest and sat down by the side of the cool
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;fountain; and when she was bored she took a golden ball,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;and threw it up on high and caught it; and this ball was her
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;favorite plaything.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sr&#34;&gt;/\s+/g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;trim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fontsource&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fontSource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;location&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;CrimsonPro-Regular.ttf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ff&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newFontFamily&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;ff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addMember&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fontsource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fontWeight400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fontStyleNormal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;para&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;para&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;settings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;settingSize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;bag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;factor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;para&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;formatParagraph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;para&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;bag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mustSP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;125pt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;leading&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;14&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;bag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;factor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;fe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;family&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newPage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;outputAt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mustSP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1cm&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;bag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mustSP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;26cm&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shipout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;finish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which look familiar when you know at the &lt;a href=&#34;https://boxesandglue.dev/gettingstarted/installation/&#34;&gt;“getting started” document&lt;/a&gt; in the manual.&lt;/p&gt;
&lt;p&gt;Tun run the JavaScript file above, you need to download the software ets (&lt;a href=&#34;https://github.com/boxesandglue/ets/blob/main/Readme.md#installation&#34;&gt;see the Readme file in the repository&lt;/a&gt;), &lt;a href=&#34;https://github.com/boxesandglue/boxesandglue-examples/tree/main/fonts/crimsonpro&#34;&gt;download the font&lt;/a&gt; and run&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ets myfile.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;on the command line.&lt;/p&gt;
&lt;p&gt;This produces two files (hopefully): a PDF file (&lt;code&gt;out.pdf&lt;/code&gt; in this case) and a log file (&lt;code&gt;ets-protocol.xml&lt;/code&gt;) which contains information about errors and warning, in case something goes wrong.&lt;/p&gt;
&lt;p&gt;The JavaScript bindings are documented at &lt;a href=&#34;https://boxesandglue.dev/ets/&#34;&gt;boxesandglue.dev/ets/&lt;/a&gt;. Examples &lt;a href=&#34;https://github.com/boxesandglue/boxesandglue-examples/tree/main/ets&#34;&gt;are found in a repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Currently ets is at version 0.0.2, you can conclude from that version number that this is still in the beginning of development. My next steps are including input and output of regular files, a JSON and XML reader as well as http-bindings to access assets without download.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>New XPath variables semantics</title>
      <link>https://news.speedata.de/2024/09/04/setvariablesemantic/</link>
      <pubDate>Tue, 03 Sep 2024 20:21:36 +0200</pubDate>
      
      <guid>https://news.speedata.de/2024/09/04/setvariablesemantic/</guid>
      <description>&lt;p&gt;Something that was a bit inconsistent for a while is variable assignments of element structures.&lt;/p&gt;
&lt;p&gt;Take this snippet for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;SetVariable&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;variable=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myvar&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Element&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attr&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#39;foo1&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Element&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Element&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Bar&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attr&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#39;bar1&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Element&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/SetVariable&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, what exactly is the contents of &lt;code&gt;$myvar&lt;/code&gt;? With the old XPath parser, this used to be a table with two entries (two elements). But inconsistent: Both &lt;code&gt;count($myvar)&lt;/code&gt; and &lt;code&gt;count($myvar/Foo)&lt;/code&gt; return 2, which is incorrect in both cases.&lt;/p&gt;
&lt;p&gt;From now on (the new XPath parser) tries to stay as close as possible to the XPath / XSLT standards. &lt;code&gt;count($myvar)&lt;/code&gt; now returns 1 (the XML fragment) and &lt;code&gt;count($myvar/Foo)&lt;/code&gt; returns 1 (the element node &lt;code&gt;Foo&lt;/code&gt;), and &lt;code&gt;count($myvar/*)&lt;/code&gt; returns 2 (all element nodes in the fragment &lt;code&gt;$myvar&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This would be the equivalent in XSLT:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;xsl:variable&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myvar&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Foo&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;attr=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;foo2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;Bar&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;attr=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;bar1&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/xsl:variable&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;xsl:message&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;count($myvar)&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;xsl:message&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;count($myvar/Foo)&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;xsl:message&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;count($myvar/*)&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which prints out the messages &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt;, as expected.&lt;/p&gt;
&lt;p&gt;This looks a bit hair-splitting, but has quite a few consequences, which have incompatible backwards behavior.&lt;/p&gt;
&lt;h2 id=&#34;breaking-backwards-compatibility&#34;&gt;Breaking backwards compatibility&lt;/h2&gt;
&lt;p&gt;Breaking backwards compatibility is something I really try to avoid, but in this case I cannot see a way around it. The good news is that you can always switch to the old behavior by setting &lt;code&gt;xpath=luxor&lt;/code&gt; in the configuration file. And for new projects, you will have a much more sensible setup.&lt;/p&gt;
&lt;h2 id=&#34;show-me-the-pitfalls&#34;&gt;Show me the pitfalls&lt;/h2&gt;
&lt;p&gt;Every time you access a variable that has a data structure (constructed with &lt;code&gt;&amp;lt;Element&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Attribute&amp;gt;&lt;/code&gt; commands), you need to have an explicit node selector.&lt;/p&gt;
&lt;p&gt;All commands that use the attributes &lt;code&gt;select&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; are affected. See the &lt;a href=&#34;https://github.com/speedata/examples/tree/master/technical/index&#34;&gt;index example&lt;/a&gt; in the &lt;a href=&#34;https://github.com/speedata/examples/&#34;&gt;GitHub repository&lt;/a&gt;. It now has&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;Makeindex&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;$indexentries/indexentry&amp;#34;&lt;/span&gt;  &lt;span class=&#34;err&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;instead of&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;Makeindex&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;$indexentries&amp;#34;&lt;/span&gt;  &lt;span class=&#34;err&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Explanation: the variable &lt;code&gt;$indexentries&lt;/code&gt; is constructed as follows (in a loop):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;SetVariable&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;variable=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;indexentries&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Copy-of&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;$indexentries&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Element&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;indexentry&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;@word&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;page&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;@page&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Element&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/SetVariable&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;so it is an XML fragment containing several nodes of type element. To get all of these elements, an explicit selection of &lt;code&gt;$indexentries/indexentry&lt;/code&gt; is necessary.&lt;/p&gt;
&lt;p&gt;Also &lt;code&gt;&amp;lt;ProcessNode select=&amp;quot;$index&amp;quot; /&amp;gt;&lt;/code&gt; has been changed to &lt;code&gt;&amp;lt;ProcessNode select=&amp;quot;$index/index&amp;quot; /&amp;gt;&lt;/code&gt; because the former just selects the (unnamed) XML fragment and the latter selects a sequence of elements which gets processed individually.&lt;/p&gt;
&lt;p&gt;A bit surprisingly comes &lt;code&gt;&amp;lt;Copy-of&amp;gt;&lt;/code&gt;, although it is not a special case.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;SetVariable&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;variable=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myvar&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Element&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attr&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#39;foo1&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Element&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Element&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Bar&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attr&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#39;bar1&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Element&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/SetVariable&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;SetVariable&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;variable=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myvar2&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Copy-of&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;$myvar&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Element&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attr&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#39;foo2&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Element&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/SetVariable&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The variable &lt;code&gt;$myvar2&lt;/code&gt; now contains a copy of &lt;code&gt;$myvar&lt;/code&gt; and an additional element &lt;code&gt;Foo&lt;/code&gt;. You could also explicitly select the desired nodes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;SetVariable&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;variable=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myvar2&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Copy-of&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;$myvar/Foo&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Element&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Attribute&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attr&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#39;foo2&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Element&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/SetVariable&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Both ways (&lt;code&gt;$myvar&lt;/code&gt; and &lt;code&gt;$myvar/Foo&lt;/code&gt;) work. The first expression, which selects the whole fragment, works by copying the contents of the fragment to the result sequence, and the second expression explicitly selects the two elements which are copied to the result sequence.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;If you have an old layout, you can keep using it by selecting the old XPath parser. If you use the new XPath parser, make sure you update your code if you use the &lt;code&gt;&amp;lt;Element&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Attribute&amp;gt;&lt;/code&gt; commands.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Microtypography and
font expansion</title>
      <link>https://news.speedata.de/2024/07/11/fontexpansion/</link>
      <pubDate>Thu, 11 Jul 2024 12:38:01 +0200</pubDate>
      
      <guid>https://news.speedata.de/2024/07/11/fontexpansion/</guid>
      <description>&lt;p&gt;The speedata Publisher is built on top of LuaT&lt;span class=&#34;TeX-e&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;TeX-x&#34;&gt;X&lt;/span&gt;, a typesetting software with a strong focus on typography.
Therefore it inherits all the possibilities offered by the layout engine.
One of the older features is the ability to stretch or shrink glyph widths on demand to allow even better line breaking.&lt;/p&gt;
&lt;p&gt;T&lt;span class=&#34;TeX-e&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;TeX-x&#34;&gt;X&lt;/span&gt; already uses the famous line breaking algorithm that optimizes the appearance of a full paragraph as a whole, not a line-by-line approach that might lead to large inter-word spacing.&lt;/p&gt;
&lt;p&gt;The ability to stretch or shrink glyphs by a little amount can lead to many more possible line breaks and thus enhancing the overall visual outcome of a paragraph. The famous Gutenberg 42 line bible (B42) has a &lt;a href=&#34;https://finaltype.de/en/topics/gutenbergs-justification#gutenbergs-justification&#34;&gt;similar approach to line breaking&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The speedata Publisher by default uses a little percentage to stretch or shrink glyphs.
This helps text in narrow columns to be typeset nicely.&lt;/p&gt;
&lt;h2 id=&#34;the-speedata-publisher&#34;&gt;The speedata Publisher&lt;/h2&gt;
&lt;p&gt;As mentioned above, the speedata Publisher turns on font expansion by default. The option &lt;code&gt;fontexpansion&lt;/code&gt; is used to control this behavior:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;Options&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;fontexpansion=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;yes&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The allowed settings are:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;no&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;All characters retain the width specified by the font designer.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;some&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;The line break is carried out with the original widths, after the break the characters can be changed slightly in width so that the spaces between the words are slightly reduced.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;(default setting) The paragraph break is tried out with different character widths and then the best result is used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;To see the effect of &lt;code&gt;some&lt;/code&gt;, here is a German text that is typeset with &lt;code&gt;none&lt;/code&gt; (left) and &lt;code&gt;some&lt;/code&gt; (middle) and a comparison of both (right), where the green text is identical to the middle example. German texts are known to have long words&amp;hellip;&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2024/07/11/fontexpansion/fontexpansionsome.png&#34;  /&gt;
        
    
    
    &lt;div class=&#34;caption&#34;&gt;
        &lt;p&gt;Text typeset with font expansion off (left), some (middle) and a comparison (right)&lt;/p&gt;
        
    &lt;/div&gt;
    
&lt;/figure&gt;


&lt;p&gt;The result of &lt;code&gt;yes&lt;/code&gt; is more drastic. Many more possible line breaks can be considered if words can be squeezed a little to fit in to a line or stretched so the inter word spacing would be a little smaller. See the following figure. With &lt;code&gt;fontexpansion=&amp;quot;yes&amp;quot;&lt;/code&gt; you have to experiment a little to determine a good degree of stretching and compression so that the paragraphs also look &amp;ldquo;good&amp;rdquo;. On the left, &lt;code&gt;fontexpansion&lt;/code&gt; is set to &lt;code&gt;no&lt;/code&gt;, for the other two to &lt;code&gt;yes&lt;/code&gt;. The paragraph on the right is set with the values 5% stretch and 3% compress (50 and 30 for &lt;code&gt;fontstretch&lt;/code&gt; and &lt;code&gt;fontshrink&lt;/code&gt;).&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2024/07/11/fontexpansion/fontexpansionyes.png&#34;  /&gt;
        
    
    
    &lt;div class=&#34;caption&#34;&gt;
        &lt;p&gt;Text typeset with font expansion no (left) and yes (middle and right). The text to the right has higher values for stretching and shrinking.&lt;/p&gt;
        
    &lt;/div&gt;
    
&lt;/figure&gt;


&lt;p&gt;You can influence the values either on a font basis or via the global &lt;code&gt;&amp;lt;Options&amp;gt;&lt;/code&gt; command.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;fontstretch&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;Specifies the percentage by which the characters may be stretched. Specification is in 0.1 per cent: a value of 20 means 2%. The default setting is 40 (= 4%).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;fontshrink&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;Like &lt;code&gt;fontstretch&lt;/code&gt;, only as an indication of the compression. The default setting is 30 (= 3%).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;fontstep&lt;/code&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;The steps in which the wrapping algorithm &#34;tries out&#34; the stretching or compression. The default setting is 10.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;These settings are also available for &lt;a href=&#34;https://doc.speedata.de/publisher/en/commandreference/loadfontfile/#cmd-loadfontfile&#34;&gt;&lt;code&gt;&amp;lt;LoadFontfile&amp;gt;&lt;/code&gt;&lt;/a&gt; (without the &lt;code&gt;font&lt;/code&gt; prefix), but beware that the settings must be the same for all fonts in a paragraph.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>speedata Publisher and accessibility</title>
      <link>https://news.speedata.de/2024/06/17/speedatapublishera11y/</link>
      <pubDate>Mon, 17 Jun 2024 09:28:42 +0200</pubDate>
      
      <guid>https://news.speedata.de/2024/06/17/speedatapublishera11y/</guid>
      <description>&lt;p&gt;Version 4.19.8 has a completely written module for creating tagged PDF for accessibility.&lt;/p&gt;
&lt;p&gt;First, you need to set the output format to PDF/UA with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;PDFOptions&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;format=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;PDF/UA&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tagged PDF also needs an outline of the structure of the document. See the &lt;a href=&#34;https://news.speedata.de/2024/06/11/insidepdf-06/&#34;&gt;previous blog entry for more details on tagged PDF&lt;/a&gt;. To summarize: you create an description of what is visible in the PDF. Each visible part gets tagged with a structure type (“this is a label for a table of contents link”, “this is a heading” and so on).&lt;/p&gt;
&lt;p&gt;The new command &lt;code&gt;&amp;lt;StructureElement&amp;gt;&lt;/code&gt; in the speedata Publisher adds an entry to a hierarchical list. For example&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Document&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Sect&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/StructureElement&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Sect&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/StructureElement&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/StructureElement&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;creates two sections in document, each section contains two articles. To add text or images to a structure part, you need to create a unique id for entry, for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Document&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Sect&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1a1&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1a2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/StructureElement&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Sect&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s2a1&amp;#34;&lt;/span&gt;  &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s2a2&amp;#34;&lt;/span&gt;  &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/StructureElement&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/StructureElement&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and add contents to the structure, for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;PlaceObject&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;Textblock&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Paragraph&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;H1&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1a1&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nt&#34;&gt;&amp;lt;Value&amp;gt;&lt;/span&gt;A short story&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Value&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Paragraph&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;Paragraph&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;P&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1a1&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nt&#34;&gt;&amp;lt;Value&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;select=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;sd:dummytext()&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Paragraph&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nt&#34;&gt;&amp;lt;/Textblock&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/PlaceObject&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This adds a level 1 heading and a paragraph to the first article in the first section (id s1a1).&lt;/p&gt;
&lt;p&gt;The document has the following outline:&lt;/p&gt;

&lt;figure &gt;
    
        
        &lt;img src=&#34;https://news.speedata.de/2024/06/17/speedatapublishera11y/struct.png&#34;  /&gt;
        
    
    
&lt;/figure&gt;


&lt;h2 id=&#34;dynamic-structure-elements&#34;&gt;Dynamic structure elements.&lt;/h2&gt;
&lt;p&gt;Depending on the data, you may not be able to predict the structure elements. Therefore you can add a child entry to a parent when you pass a parent id:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Document&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;doc&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Sect&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;doc&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Sect&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s2&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;doc&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1a1&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1a2&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s1&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s2a1&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Art&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s2a2&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;parent=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;s2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is equivalent to the example at the beginning.&lt;/p&gt;
&lt;h2 id=&#34;defaults&#34;&gt;Defaults&lt;/h2&gt;
&lt;p&gt;The speedata Publisher starts with a default root element:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;StructureElement&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;role=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Document&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;id=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;doc&amp;#34;&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and the default parent of each element that is placed in the PDF is &lt;code&gt;doc&lt;/code&gt;, so each element is a direct child of the document, unless you provide a different structure.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>