Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply XSLT on XML with just XInclude

Tags:

xml

xslt

xinclude

I have this XML file:

<?xml version="1.0"?>
<xi:include href="http://www.w3schools.com/dom/books.xml" 
            xmlns:xi="http://www.w3.org/2003/XInclude"/>

and I expected that it should result in referenced remote XML file http://www.w3schools.com/dom/books.xml at the time of processing.

For that purpose I created this XSL file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml"/>
    <xsl:template match="*">
        <xsl:copy-of select="//book/title"/>
    </xsl:template>
</xsl:stylesheet>

which after XSL transform, I expected to get XML output with title nodes from referenced XML file.

However it didn't happen, transformation just produced an empty file. I suspect that XInclude instruction wasn't performed.

So how can I apply XSLT on Xincluded XML file, if possible?

like image 859
theta Avatar asked Jul 17 '12 15:07

theta


1 Answers

In comments, the OP has asked for a walk-through of my referenced answer at Copy xml document's images in different source locations into single output directory , so here it is.

This template..

<xsl:template match="xi:include[@href][@parse='xml' or not(@parse)][fn:unparsed-text-available(@href)]">
 <xsl:apply-templates select="fn:document(@href)" />
</xsl:template>

... matches the xi:include elements that meet all these requirements:

  1. Has a href attribute
  2. It refers to an xml document (as opposed to a text document)
  3. And that document can be found and is openable.

When these conditions are met, open the XML document and process it just as if it was in place here, instead of the xi:include node.

This template ...

<xsl:template match="xi:include[@href][@parse='text'][fn:unparsed-text-available(@href)]">
 <xsl:apply-templates select="fn:unparsed-text(@href,@encoding)" />
</xsl:template>

... does a similar thing for pure text includes. Note the default value for @parse is 'xml'. Note we can even change character encoding. Our main document could be in UTF-8, but the included document may well be UTF-16LE for example.

And finally this template...

<xsl:template match="xi:include[@href][@parse=('text','xml') or not(@parse)][not(fn:unparsed-text-available(@href))][xi:fallback]">
 <xsl:apply-templates select="xi:fallback/text()" />
</xsl:template>

... handles the cases where we can open the document (maybe the file reference is broken), and the xi:include node gives us some fall-back content.

like image 165
Sean B. Durkin Avatar answered Oct 16 '22 12:10

Sean B. Durkin