OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Namespace Catalogue Hackery (long, mostly code)



In honor of the similarly named SW thread...

So I was thinking more about implementing nameapace catalogs in XSLT, and
of course extensions aren't necessary.  Here is some hackery on the
concept.  I flipped a three-sided coin in my head to pick from the
proposals and ended up with Sean Palmer's.  Should be easy enough modify
for the other catalog proposals.


<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ft="http://namespaces.4suite.org/xpath/extensions"
  xmlns:html="http://www.w3.org/1999/xhtml"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  version="1.0"
>

  <!--    SNIP    -->

  <xsl:key
    name="redirects"
    match="processing-instruction('namepace-resolution-redirect')"
    use="substring-before(substring-after(., 'from=&quot;'), '&quot;')"/>

  <xsl:template name="get-ns-catalogue-resources">
    <xsl:param name="uri"/>
    <xsl:variable name="catalog-uri">
      <xsl:choose>
        <xsl:when test="key('redirects', $uri)">
          <xsl:value-of select="substring-before(substring-after(key('redirects', $uri), 'to=&quot;'), '&quot;')"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$uri"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:message>Retrieving namespace catalog from: <xsl:value-of select="$catalog-uri"/></xsl:message>
    <xsl:variable name="ns-cat" select="document($catalog-uri)"/>

    <xsl:for-each select="$ns-cat/html:html/html:head/html:link[html:div and @rel='meta']">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="ft:copy"/>
      </xsl:copy>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="node()" mode="ft:copy">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" mode="ft:copy"/>
    </xsl:copy>
  </xsl:template>

  <!--    SNIP    -->

  <xsl:template match="/">
    <xsl:apply-templates select="*/namespace::*[not(name()='xml')]" mode="NSRef"/>
  </xsl:template>

  <xsl:template match="node()" mode="NSRef">
    <xsl:variable name="ns-link-rtf">
      <xsl:call-template name="get-ns-catalogue-resources">
        <xsl:with-param name="uri" select="."/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="ns-link" select="ft:node-set($ns-link-rtf)"/>

    Content type: <xsl:value-of select="$ns-link/@type"/><xsl:text>&#10;</xsl:text>
    href: <xsl:value-of select="$ns-link/@href"/><xsl:text>&#10;</xsl:text>
    xlink:href: <xsl:value-of select="$ns-link/html:div/@xlink:href"/><xsl:text>&#10;</xsl:text>
    xlink:arcrole: <xsl:value-of select="$ns-link/html:div/@xlink:arcrole"/><xsl:text>&#10;</xsl:text>
    xlink:title: <xsl:value-of select="$ns-link/html:div/@xlink:title"/><xsl:text>&#10;</xsl:text>
  </xsl:template>

</xsl:stylesheet>


Here is my sample namespace catalog, nscat.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xlink="http://www.w3.org/1999/xlink">
  <head>
  <link rel="meta" xncl:type="ncl" type="application/rdf"
href="myschema.rdf">
      <div xlink:type="simple"
         xlink:href="myschema.rdf"
         xlink:arcrole="http://www.w3.org/2000/01/RDF-Schema"
         xlink:title="RDF Schema"/>
  </link>
  </head>
  <body>
    SpamEggs
  </body>
</html>


Here is the sample source, test.xml:

<foo xmlns="http://spam.com">
  <?namepace-resolution-redirect from="http://spam.com" to="nscat.xhtml"?>
  <bar/>
</foo>


And here we go:

[uogbuji@borgia ns-catalogues]$ 4xslt test.xml get-ns-catalogue.xslt
STYLESHEET MESSAGE:
Retrieving namespace catalog from: nscat.xhtml
END STYLESHEET MESSAGE:
<?xml version='1.0' encoding='UTF-8'?>


    Content type: application/rdf

    href: myschema.rdf

    xlink:href: myschema.rdf

    xlink:arcrole: http://www.w3.org/2000/01/RDF-Schema

    xlink:title: RDF Schema


[uogbuji@borgia ns-catalogues]$


Notes:

1) This little jaunt exposed some silly bugs in 4XSLT <deep sigh>.  I've
fixed them all, but if you're using 4XSLT for this, you'll need tonight's
CVS snapshot.

2) Looks as if I immediately found use for the processing-instruction
redirect trick I mentioned to Miles Sabin.  I didn't want to set up a
namespace catalog on some remote server just for this quick hack, so I
went and used a bogus namespace URI and then used the PI to redirect it to
a file on my local disk.  Technically, I couldn't just use this local file
directly as the namespace because of the bar on relative URIs as NSRef.

3) I use ft:node-set, which converts result tree fragments to node sets.
Almost every XSLT processor provides an equivalent extension function.
Modify accordingly.

4) You can use this for your own stuff by copying the code between the
"SNIP" comments.

5) The xsl:key isn't really necessary (XT users take note).  You can
instead use pull or push methods to retrieve all the redirect PIs from the
XPath "//processing-instruction('namepace-resolution-redirect')".

6) Note that I explicitly ignore the xml namespace, which is always
in the namespace axis.  This is because the result of dereffing this
namespace ("http://www.w3.org/XML/1998/namespace") returns HTML, which is
technically illegal for input to document().


-- 
Uche Ogbuji                               Principal Consultant
uche.ogbuji@fourthought.com               +1 303 583 9900 x 101
Fourthought, Inc.                         http://Fourthought.com
4735 East Walnut St, Ste. C, Boulder, CO 80301-2537, USA
Software-engineering, knowledge-management, XML, CORBA, Linux, Python