Search code examples
xmlxsltxinclude

Do mapping between xml:base attribute and other node values of a xml file using XSLT 1.0


I am having a xml document like below,

<chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter1">
<title>First chapter</title>
<section xml:id="section1">
                <imageobject>
                    <imagedata fileref="images/image1.jpg"/>
                </imageobject>
                <imageobject>
                    <imagedata fileref="images/image5.jpg"/>
                </imageobject>
</section>
    <chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter2"   xml:base="../foder1/section2.xml">        
   <section xml:id="section2">
                    <imageobject>
                        <imagedata fileref="images/image2.jpg"/>
                    </imageobject>
                    <imageobject>
                        <imagedata fileref="images/image3.jpg"/>
                    </imageobject>
    </section>
    </chapter>
    <chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter3" xml:base="../folder3/section3.xml">  
   <section xml:id="section3">
                    <imageobject>
                        <imagedata fileref="images/image4.jpg"/>
                    </imageobject>
    </section>
   </chapter>
 </chapter>

As in file, there are relative paths to the images in each xincluded file. I want to get the absolute path of the image. For that I am going to combine xml:base value of each chapter with the relative image paths in that chapter. Then I can get all absolute paths to images in each chapter. For that purpose I used following XSLT 1.o file.

<xsl:template match="/">
<imagepaths>
<xsl:for-each select="chapter/chapter">
 <basepath>
 <xsl:value-of select="@xml:base"/>
 </basepath>
</xsl:for-each>
 <xsl:apply-templates select="*" /> 
</image-paths>
</xsl:template>

  <xsl:template match="*">
  <xsl:apply-templates select="*" />
   </xsl:template>

   <xsl:template match="imagedata">
  <relativepath>
  <xsl:value-of select="@fileref" />
  </realtivepath>
  </xsl:template>
  </xsl:stylesheet>

But this gives all xml:base values and relative paths separately. It does not provide any mapping between xml:base value of each chapter and relative paths in that chapter. I want to have a mapping between xml:base value and all relative paths in that chapter. How I this mapping should do? I think by having output like below, I can do the mapping and get the absolute path of images. Please help me to get following output with my XSLT. With it I can access all images in section1 by "mainrelativepath" and section2, section3 images by basepath and relativepath nodes.

<Imagedata>
    <mainrelativepath>images/image1.jpg</mainrelativepath>
    <mainrelativepath>images/image5.jpg</mainrelativepath>
<chapter>
    <basepath>../foder1/section2.xml</basepath>
    <relativepath>images/image2.jpg</relativepath>
    <relativepath>images/image3.jpg</relativepath>
</chapter>
<chapter>
    <basepath>../foder3/section3.xml</basepath>
    <relativepath>images/image4.jpg</relativepath>
</chapter>

Thanks in advance..!!


Solution

  • This transformation:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/*">
      <Imagedata>
        <xsl:apply-templates select="chapter"/>
      </Imagedata>
     </xsl:template>
    
     <xsl:template match="*/chapter">
      <chapter>
       <basepath><xsl:value-of select="@xml:base"/></basepath>
       <xsl:apply-templates/>
      </chapter>
     </xsl:template>
    
     <xsl:template match="imagedata">
       <relativepath><xsl:value-of select="@fileref"/></relativepath>
     </xsl:template>
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    

    when applied on the provided XML document:

    <chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter1">
        <title>First chapter</title>
        <section xml:id="section1">
                        <imageobject>
                            <imagedata fileref="images/image1.jpg"/>
                        </imageobject>
        </section>
            <chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter2"   xml:base="../foder1/section2.xml">
           <section xml:id="section2">
                            <imageobject>
                                <imagedata fileref="images/image2.jpg"/>
                            </imageobject>
                            <imageobject>
                                <imagedata fileref="images/image3.jpg"/>
                            </imageobject>
            </section>
            </chapter>
            <chapter xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="chapter3" xml:base="../folder3/section3.xml">
           <section xml:id="section3">
                            <imageobject>
                                <imagedata fileref="images/image4.jpg"/>
                            </imageobject>
            </section>
           </chapter>
    </chapter>
    

    produces the wanted, correct result:

    <Imagedata>
       <chapter>
          <basepath>../foder1/section2.xml</basepath>
          <relativepath>images/image2.jpg</relativepath>
          <relativepath>images/image3.jpg</relativepath>
       </chapter>
       <chapter>
          <basepath>../folder3/section3.xml</basepath>
          <relativepath>images/image4.jpg</relativepath>
       </chapter>
    </Imagedata>