commit:     bc2e4a7c7f83310ff46f1cf489fea0249ef63137
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Mon Oct 30 17:45:02 2023 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
CommitDate: Thu Nov  2 17:03:11 2023 +0000
URL:        https://gitweb.gentoo.org/proj/devmanual.git/commit/?id=bc2e4a7c

depend.xsl: Canonicalise output paths

Convert to absolute paths in XSLT, so postprocessing with sed is
no longer needed.

Signed-off-by: Ulrich Müller <ulm <AT> gentoo.org>

 Makefile   |  2 +-
 depend.xsl | 23 +++++++++++++++--------
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/Makefile b/Makefile
index 89874ae..e75cbf1 100644
--- a/Makefile
+++ b/Makefile
@@ -74,7 +74,7 @@ appendices/todo-list/index.html: $(XMLS)
 # Generate the list of dependencies with XSLT, which appears to be a
 # better tool for this than make.
 .depend: $(XMLS) eclass-reference/text.xml depend.xsl devbook.xsl
-       @xsltproc depend.xsl $(XMLS) | sed ':x;s%[^ /]*/\.\./%%;tx' > $@
+       @xsltproc depend.xsl $(XMLS) > $@
 
 install: all
        set -e; \

diff --git a/depend.xsl b/depend.xsl
index abb139a..15c5e15 100644
--- a/depend.xsl
+++ b/depend.xsl
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+  xmlns:str="http://exslt.org/strings";
   xmlns:exslt="http://exslt.org/common";
-  extension-element-prefixes="exslt xsl"
-  exclude-result-prefixes="exslt xsl">
+  extension-element-prefixes="str exslt xsl"
+  exclude-result-prefixes="str exslt xsl">
 
 <xsl:import href="devbook.xsl"/>
 <xsl:output method="text"/>
@@ -20,12 +21,18 @@
   <xsl:variable name="self" select="/guide/@self"/>
   <xsl:value-of select="concat($self, 'index.html:')"/>
   <xsl:for-each select="exslt:node-set($refs)//a/@href[. != '#']">
-    <!-- At this point, the path can contain ".." components and
-         should be canonicalised, but string processing in XPath 1.0
-         sucks (no pattern matching!). It is easier to pipe the output
-         through sed instead. -->
-    <xsl:value-of select="concat(' ', $self,
-        substring-before(., 'index.html'), 'text.xml')"/>
+    <xsl:text> </xsl:text>
+    <xsl:variable name="path" select="substring-before(., 'index.html')"/>
+    <!-- At this point, $path can start with zero or more ".." components
+         and is relative to $self. Convert it to an absolute path. -->
+    <xsl:variable name="up" select="count(str:tokenize($path, '/')[. = 
'..'])"/>
+    <xsl:for-each select="str:tokenize($self, '/')[position() &lt;= last() - 
$up]">
+      <xsl:value-of select="concat(., '/')"/>
+    </xsl:for-each>
+    <xsl:for-each select="str:tokenize($path, '/')[position() &gt; $up]">
+      <xsl:value-of select="concat(., '/')"/>
+    </xsl:for-each>
+    <xsl:text>text.xml</xsl:text>
   </xsl:for-each>
   <xsl:value-of select="$newline"/>
 </xsl:template>

Reply via email to