Skip to content

Commit 369007b

Browse files
committed
XSLT: Refactor chunking output
1 parent 394957e commit 369007b

1 file changed

Lines changed: 248 additions & 62 deletions

File tree

src/docbuild/config/xml/data/convert-v6-to-v7.xsl

Lines changed: 248 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
- portal configuration XML file (version 7)
1313
1414
Parameters:
15-
- None / TBD
15+
- use.xincludes: Whether to use xi:include for chunking output (default: true)
16+
- outputdir: The directory to write output files to (default: 'output/')
17+
- outputfile: The main output filename (default: 'portal.xml')
18+
- schemaversion: The schemaversion attribute to set in the output XML (default: '7.0')
1619
1720
Author:
1821
Tom Schraitle
@@ -23,17 +26,22 @@
2326
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
2427
xmlns:xi="http://www.w3.org/2001/XInclude"
2528
xmlns:exsl="http://exslt.org/common"
26-
exclude-result-prefixes="exsl">
29+
exclude-result-prefixes="exsl"
30+
extension-element-prefixes="exsl">
2731

2832
<xsl:output encoding="UTF-8" indent="yes" method="xml"/>
2933
<xsl:preserve-space elements="*"/>
34+
<xsl:strip-space elements="product"/>
3035

3136
<!-- ======== Parameters -->
3237
<xsl:param name="use.xincludes" select="true()" />
3338

3439
<!-- Set the output directory -->
3540
<xsl:param name="outputdir" select="'output/'" />
3641

42+
<!-- Set the main output filename -->
43+
<xsl:param name="outputfile" select="'portal.xml'" />
44+
3745
<!-- Set the schemaversion attribute in the output XML -->
3846
<xsl:param name="schemaversion">7.0</xsl:param>
3947

@@ -79,6 +87,101 @@
7987
<xsl:variable name="config" select="exsl:node-set($_transformation-map)/*" />
8088

8189

90+
<!-- ======== Helper functions -->
91+
<!--
92+
Template: write.file
93+
Writes content to a file.
94+
Parameters:
95+
filename - The filename to write to
96+
content - The content to write
97+
method - Output method (default: xml)
98+
encoding - Output encoding (default: UTF-8)
99+
indent - Whether to indent output (default: yes)
100+
-->
101+
<xsl:template name="write.file">
102+
<xsl:param name="filename"/>
103+
<xsl:param name="content"/>
104+
<xsl:param name="debug" select="1" />
105+
<xsl:param name="method" select="'xml'"/>
106+
<xsl:param name="encoding" select="'UTF-8'"/>
107+
<xsl:param name="indent" select="'yes'"/>
108+
109+
<exsl:document href="{$filename}"
110+
method="{$method}"
111+
encoding="{$encoding}"
112+
indent="{$indent}">
113+
<xsl:copy-of select="$content"/>
114+
</exsl:document>
115+
<xsl:if test="boolean($debug)">
116+
<xsl:message>Written file: <xsl:value-of select="concat('&quot;', $filename, '&quot;')" /></xsl:message>
117+
</xsl:if>
118+
</xsl:template>
119+
120+
<!--
121+
Template: write.chunk
122+
Handles the logic for writing a chunk to a file or inlining it.
123+
Parameters:
124+
filename - The relative path to the output file (from outputdir)
125+
hreftype - The href to use for xi:include
126+
Possible values: 'filename' (default), 'relative', 'none'
127+
content - The content to Write
128+
-->
129+
<xsl:template name="write.chunk">
130+
<xsl:param name="filename"/>
131+
<xsl:param name="hreftype" select="'filename'"/>
132+
<xsl:param name="manual_href" select="''"/>
133+
<xsl:param name="content"/>
134+
135+
<xsl:choose>
136+
<xsl:when test="(string($use.xincludes) = 'true' or string($use.xincludes) = '1') and $filename != ''">
137+
<xsl:variable name="href">
138+
<xsl:choose>
139+
<xsl:when test="string($manual_href) != ''">
140+
<xsl:value-of select="$manual_href"/>
141+
</xsl:when>
142+
<xsl:when test="$hreftype = 'relative'">
143+
<xsl:call-template name="substring-after-last">
144+
<xsl:with-param name="string" select="$filename"/>
145+
<xsl:with-param name="char" select="'/'"/>
146+
</xsl:call-template>
147+
</xsl:when>
148+
<xsl:otherwise>
149+
<xsl:value-of select="$filename"/>
150+
</xsl:otherwise>
151+
</xsl:choose>
152+
</xsl:variable>
153+
154+
<xi:include href="{$href}"/>
155+
156+
<xsl:call-template name="write.file">
157+
<xsl:with-param name="filename" select="concat($outputdir, $filename)"/>
158+
<xsl:with-param name="content" select="$content"/>
159+
</xsl:call-template>
160+
</xsl:when>
161+
<xsl:otherwise>
162+
<xsl:copy-of select="$content"/>
163+
</xsl:otherwise>
164+
</xsl:choose>
165+
</xsl:template>
166+
167+
<xsl:template name="substring-after-last">
168+
<xsl:param name="string" />
169+
<xsl:param name="char" />
170+
<xsl:choose>
171+
<xsl:when test="contains($string, $char)">
172+
<xsl:call-template name="substring-after-last">
173+
<xsl:with-param name="string" select="substring-after($string, $char)" />
174+
<xsl:with-param name="char" select="$char" />
175+
</xsl:call-template>
176+
</xsl:when>
177+
<xsl:otherwise>
178+
<xsl:value-of select="$string" />
179+
</xsl:otherwise>
180+
</xsl:choose>
181+
</xsl:template>
182+
183+
184+
82185
<!-- ======== General Templates -->
83186
<xsl:template match="node() | @*" name="copy">
84187
<xsl:copy>
@@ -95,78 +198,161 @@
95198

96199
<!-- ======== Templates -->
97200
<xsl:template match="/docservconfig">
98-
<portal schemaversion="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
99-
<xsl:apply-templates select="categories" />
100-
<productfamilies>
101-
<item id="linux">Linux</item>
102-
<item id="cn">Cloud Native</item>
103-
<item id="suse-edge">SUSE Edge</item>
104-
<item id="suse-ai">SUSE AI</item>
105-
</productfamilies>
106-
<series>
107-
<item id="pas">Products &amp; Solutions</item>
108-
<item id="sbp" >SUSE Best Practices</item>
109-
<item id="trd">Technical References</item>
110-
<item id="rn">Release Notes</item>
111-
</series>
112-
<xsl:apply-templates select="*[not(self::categories)]" />
113-
</portal>
201+
<xsl:call-template name="write.file">
202+
<xsl:with-param name="filename" select="concat($outputdir, $outputfile)" />
203+
<xsl:with-param name="content">
204+
<portal schemaversion="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
205+
<xsl:apply-templates select="categories" />
206+
<productfamilies>
207+
<item id="linux">Linux</item>
208+
<item id="cn">Cloud Native</item>
209+
<item id="suse-edge">SUSE Edge</item>
210+
<item id="suse-ai">SUSE AI</item>
211+
</productfamilies>
212+
<series>
213+
<item id="pas">Products &amp; Solutions</item>
214+
<item id="sbp" >SUSE Best Practices</item>
215+
<item id="trd">Technical References</item>
216+
<item id="rn">Release Notes</item>
217+
</series>
218+
<!-- <xi:include href="categories.xml" />
219+
<xsl:element name="include" namespace="http://www.w3.org/2001/XInclude">
220+
<xsl:attribute name="href">categories.xml</xsl:attribute>
221+
</xsl:element>
222+
-->
223+
<xsl:apply-templates select="*[not(self::categories)]" />
224+
</portal>
225+
</xsl:with-param>
226+
</xsl:call-template>
114227
</xsl:template>
115228

116229
<xsl:template match="/docservconfig/categories">
117-
<xsl:copy>
118-
<!-- 1. Select only the first occurring <language> element for each unique @lang -->
119-
<xsl:for-each select="category/language[generate-id() = generate-id(key('langKey', @lang)[2])]">
230+
<xsl:variable name="content">
231+
<xsl:apply-templates select="." mode="render"/>
232+
</xsl:variable>
233+
234+
<xsl:call-template name="write.chunk">
235+
<xsl:with-param name="filename" select="'categories.xml'"/>
236+
<xsl:with-param name="content" select="$content"/>
237+
</xsl:call-template>
238+
</xsl:template>
120239

121-
<!-- Store the current language code -->
240+
<xsl:template match="/docservconfig/categories" mode="render">
241+
<categories xmlns:xi="http://www.w3.org/2001/XInclude">
242+
<xsl:copy-of select="@*"/>
243+
<!-- Select only the first occurring <language> element for each unique @lang -->
244+
<xsl:for-each select="category/language[generate-id() = generate-id(key('langKey', @lang)[1])]">
122245
<xsl:variable name="currentLang" select="@lang" />
123246

124-
<!-- Create the new <category> element grouped by language -->
125-
<xsl:text>&#10; </xsl:text>
126-
<category lang="{$currentLang}">
127-
128-
<!-- Convert default="1" to default="true" to match your target XML -->
129-
<xsl:if test="@default = '1'">
130-
<xsl:attribute name="default">true</xsl:attribute>
131-
</xsl:if>
132-
133-
<!-- 3. Retrieve all <language> elements that match the current @lang -->
134-
<xsl:for-each select="key('langKey', $currentLang)">
135-
<!-- Create an <entry> for each, pulling categoryid from its parent -->
136-
<xsl:text>&#10; </xsl:text>
137-
<entry categoryid="{../@categoryid}" title="{@title}" />
138-
</xsl:for-each>
139-
<xsl:text>&#10; </xsl:text>
140-
</category>
247+
<xsl:variable name="content">
248+
<!-- Create the new <category> element grouped by language -->
249+
<category lang="{$currentLang}">
250+
251+
<!-- Retrieve all <language> elements that match the current @lang -->
252+
<xsl:for-each select="key('langKey', $currentLang)">
253+
<!-- Create an <language> for each, pulling categoryid from its parent -->
254+
<language id="{../@categoryid}" title="{@title}" />
255+
</xsl:for-each>
256+
</category>
257+
</xsl:variable>
258+
259+
<xsl:call-template name="write.chunk">
260+
<xsl:with-param name="filename" select="concat('categories/', $currentLang, '.xml')"/>
261+
<xsl:with-param name="content" select="$content"/>
262+
</xsl:call-template>
141263
</xsl:for-each>
142-
<xsl:text>&#10;</xsl:text>
143-
</xsl:copy>
144-
<xsl:text>&#10; </xsl:text>
264+
</categories>
145265
</xsl:template>
146266

147267
<!-- Product -->
148268
<xsl:template match="product">
149269
<xsl:variable name="id" select="@productid" />
150270
<xsl:variable name="cnfg" select="$config/product[@id=$id]" />
151-
<!-- <xsl:variable name="filename" select="concat($id, '.xml')" />
152271

153-
<xi:include href="{$filename}" />
154-
-->
272+
<!-- Define the subpath for the product file -->
273+
<xsl:variable name="subpath" select="concat($id, '/', $id, '.xml')"/>
155274

156-
<xsl:copy>
157-
<xsl:apply-templates select="@*" />
158-
<!-- Add new attributes based on the transformation map -->
159-
<xsl:attribute name="family">
160-
<xsl:value-of select="$cnfg/@family" />
161-
</xsl:attribute>
162-
<xsl:attribute name="series">
163-
<xsl:value-of select="$cnfg/@series" />
164-
</xsl:attribute>
165-
<xsl:attribute name="rank">
166-
<xsl:value-of select="$cnfg/@rank" />
167-
</xsl:attribute>
168-
<xsl:apply-templates />
169-
</xsl:copy>
275+
<!-- Capture the product content -->
276+
<xsl:variable name="content">
277+
<xsl:apply-templates select="." mode="render"/>
278+
</xsl:variable>
279+
280+
<xsl:call-template name="write.chunk">
281+
<xsl:with-param name="filename" select="$subpath"/>
282+
<xsl:with-param name="content" select="$content"/>
283+
</xsl:call-template>
284+
</xsl:template>
285+
286+
<xsl:template match="product" mode="render">
287+
<xsl:variable name="id" select="@productid" />
288+
<xsl:variable name="cnfg" select="$config/product[@id=$id]" />
289+
<product xmlns:xi="http://www.w3.org/2001/XInclude">
290+
<xsl:apply-templates select="@*" />
291+
<!-- Add new attributes based on the transformation map -->
292+
<xsl:attribute name="family">
293+
<xsl:value-of select="$cnfg/@family" />
294+
</xsl:attribute>
295+
<xsl:attribute name="series">
296+
<xsl:value-of select="$cnfg/@series" />
297+
</xsl:attribute>
298+
<xsl:attribute name="rank">
299+
<xsl:value-of select="$cnfg/@rank" />
300+
</xsl:attribute>
301+
<xsl:apply-templates select="node()[not(self::desc)]" />
302+
303+
<!-- Handle desc elements -->
304+
<xsl:if test="desc">
305+
<xsl:variable name="content">
306+
<descriptions xmlns:xi="http://www.w3.org/2001/XInclude">
307+
<xsl:for-each select="desc">
308+
<xsl:variable name="lang" select="@lang"/>
309+
<xsl:variable name="inner_content">
310+
<xsl:copy-of select="."/>
311+
</xsl:variable>
312+
313+
<xsl:call-template name="write.chunk">
314+
<xsl:with-param name="filename" select="concat($id, '/desc/', $lang, '.xml')"/>
315+
<xsl:with-param name="hreftype" select="'relative'"/>
316+
<xsl:with-param name="content" select="$inner_content"/>
317+
</xsl:call-template>
318+
</xsl:for-each>
319+
</descriptions>
320+
</xsl:variable>
321+
322+
<xsl:call-template name="write.chunk">
323+
<xsl:with-param name="filename" select="concat($id, '/desc/desc.xml')"/>
324+
<xsl:with-param name="manual_href" select="'desc/desc.xml'"/>
325+
<xsl:with-param name="content" select="$content"/>
326+
</xsl:call-template>
327+
</xsl:if>
328+
</product>
329+
</xsl:template>
330+
331+
<!-- We ignore the product/category as this was moved to portal/categories -->
332+
<xsl:template match="product/category" />
333+
334+
<!-- Docset -->
335+
<xsl:template match="docset">
336+
<xsl:variable name="id" select="ancestor::product/@productid"/>
337+
<xsl:variable name="ver" select="@setid"/>
338+
<xsl:variable name="subpath" select="concat($id, '/', $ver, '.xml')"/>
339+
340+
341+
<xsl:variable name="content">
342+
<xsl:apply-templates select="." mode="render"/>
343+
</xsl:variable>
344+
345+
<xsl:call-template name="write.chunk">
346+
<xsl:with-param name="filename" select="$subpath"/>
347+
<xsl:with-param name="hreftype" select="'relative'"/>
348+
<xsl:with-param name="content" select="$content"/>
349+
</xsl:call-template>
350+
</xsl:template>
351+
352+
<xsl:template match="docset" mode="render">
353+
<xsl:copy>
354+
<xsl:apply-templates select="node()|@*"/>
355+
</xsl:copy>
170356
</xsl:template>
171357

172358
<!-- don't copy these attributes -->
@@ -181,13 +367,12 @@
181367
</xsl:template>
182368

183369

184-
<!-- docset -->
185-
<xsl:template match="docset/@setid">
370+
<!--<xsl:template match="docset/@setid">
186371
<xsl:variable name="id" select="." />
187372
<xsl:attribute name="id">
188373
<xsl:value-of select="$id"/>
189374
</xsl:attribute>
190-
</xsl:template>
375+
</xsl:template>-->
191376

192377
<xsl:template match="docset/@schemaversion" />
193378

@@ -227,4 +412,5 @@
227412
<!-- desc -->
228413
<xsl:template match="desc/@default" />
229414

415+
230416
</xsl:stylesheet>

0 commit comments

Comments
 (0)