Search code examples
xmlxsltdocbook

How to add @xml:base to my .xml files?


I need a stylesheet to convert my docbook xml files so that they now include a xml:base element to my section tags. How do I go about doing that (since xml:base needs system and node info???)

Input:

<section xmlns="http://docbook.org/ns/docbook" xml:id="voidVisit" version="5">
<title>Void</title>

 <section>
  <title>Screenshot</title>
      <mediaobject>
          <imageobject>
              <imagedata fileref="screenshots/Dialog.png" />
          </imageobject>
      </mediaobject>
 </section>
</section>

Output:

      ...
      <section xml:id="void" version="5"
           xml:base="file:/C:/Projects/my/proj/trunk/spec/module/components/void.xml">
     <title>Void</title>
     <section>
        <title>Screenshot</title>
        <mediaobject>
           <imageobject>
              <imagedata fileref="screenshots/Dialog.png"/>
           </imageobject>
        </mediaobject>
     </section>
     ...

Solution

  • In XSLT 2.0 (XPath 2.0) the functions static-base-uri() and base-uri() can be used for this purpose.

    Here is a working example:

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes"/>
        <xsl:template match="/">
         <doc xml:base="{base-uri()}"/>
        </xsl:template>
    </xsl:stylesheet>
    

    when this transformation is applied, the wanted result is produced:

    <doc xml:base="file:/C:/CVS-DDN/fxsl-xslt2/data/marrowtr.xml"/>
    

    So, the complete transformation in your case is:

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:d="http://docbook.org/ns/docbook">
     <xsl:output omit-xml-declaration="yes"/>
    
        <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
        </xsl:template>
    
        <xsl:template match="/d:section">
         <xsl:copy>
           <xsl:attribute name="xml:base" select="base-uri(/)"/>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    In XSLT 1.0 the solution is to pass the base-uri as an external parameter (global xsl:param>) to the transformation.