[XML-DEV Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Relax NG With Classes


define xsl
Intro:
I trying to make a better RDF serialization, but Relax NG I also want to
use some Design Patterns from my favorite programming book [1].  As the
story goes, I spent a day and a half [2] figuring out a version of Relax
NG with classes.  I hacked together a stylesheet too, so it isn't just a
lame-idea.  Someone else might need something like this, or I made a
mistake.  So check it out please.

Grammar:
First you need a sort-of Relax NG document.  Some namespaces are defined
[3].  Note that the slash (or is it a backslash) at the end of &rwc; is
mandatory; it's there in case some gal or guy decides to talk about it
with RDF statements.  The document MUST begin with a grammar element,
and thus also contain a start element:

<grammar xmlns = "&rng;" xmlns:c = "&rwc;">
<start>
  <element name="hi">
    <text />
  </element>
</start>
</grammar>

The grammar element may also contain c:class elements.  These get name
attributes with NCName values that can't clash with the name of any
define elements in the current scope.  The c:class can contain start or
define elements - that's all of the Relax NG elements it can take.
Those defines and starts can reference each other, but not defines
outside the class.  Here's an example:

<grammar xmlns = "&rng;" xmlns:c = "&rwc;">
<start>
  <element name="hi">
    <ref name="A" />
  </element>
</start>
<c:class name="A">
  <start combine="choice">
    <ref name="foo" />
  </start>
  <define name="foo">
    <element name="foo">
      <ref name="bar" />
    </element>
  </define>
  <define name="bar">
    <attribute name="bar" />
  </define>
</c:class>
</grammar>

And the stylesheet (at end of email) should convert it to:

<grammar xmlns = "&rng;" xmlns:c = "&rwc;">
<start>
  <element name="hi">
    <ref name="A" />
  </element>
</start>
<define name="A">
  <grammar>
    <start combine="choice">
      <ref name="foo" />
    </start>
    <define name="foo">
      <element name="foo">
        <ref name="bar" />
      </element>
    </define>
    <define name="bar">
      <attribute name="bar" />
    </define>
  </grammar>
</define>
</grammar>

You can inherit definitions from other classes; this is done with the
c:inherit element, strangely enough.  :-)  Any definitions defined in
the inheritee class that have the same name as a definition in the
inheriter class are not imported (but the references still are).  An
exception is when the "combine" attribute is attached.  Here's an
example:

<grammar xmlns = "&rng;" xmlns:c = "&rwc;">
<start>
  <element name="hi">
    <ref name="A" />
  </element>
</start>
<c:class name="A">
  <c:inherit name="B" />
  <start>
    <ref name="foo" />
  </start>
  <define name="foo">
    <element name="foo">
      <ref name="bar" />
    </element>
  </define>
</c:class>
<c:class name="B">
  <define name="foo">
    <element name="goo">
      <attribute name="moo" />
      <text />
    </element>
  </define>
  <define name="bar">
    <attribute name="bar" />
  </define>
</c:class>
</grammar>

That should become:

<grammar xmlns = "&rng;" xmlns:c = "&rwc;">
<start>
  <element name="hi">
    <ref name="A" />
  </element>
</start>
<define name="A">
  <grammar>
    <define name="bar">
      <attribute name="bar" />
    </define>
    <start>
      <ref name="foo" />
    </start>
    <define name="foo">
      <element name="foo">
        <ref name="bar" />
      </element>
    </define>
  </grammar>
</define>
<define name="B">
  <grammar>
    <define name="foo">
      <element name="goo">
        <attribute name="moo" />
        <text />
      </element>
    </define>
    <define name="bar">
      <attribute name="bar" />
    </define>
  </grammar>
</define>
</grammar>

Notice that "bar" was imported from class-B but "foo" wasn't.  That's
because the definition in class-A overrides the one in class-B.
However, if a "combine" attribute is specified, both definitions will be
imported (since one could combine with the other.

Well, the final thing is the stylesheet; it is here [4] and here [5].
Note that abstract types and other doodads can be made with Relax NG
tricks.  Anyway, hope that's helpful.  Finally, if you want to email me,
use j f c s t 2 4 (shift-two) p i r e m o v e t t (period) e d u [darn
spammers!].  Make sure to fix the punctuation and get rid of the word
that means "get rid of".  Or use jimbolist at hotmail dot com (public).
No spam.

--
Jimmy Cerra

] "XML is just syntax, and you can therefore 
]  use it any way you like." - Michael Kay

[1] Design Patterns, urn:isbn:0-201-63361-2. It is by Erich Gamma,
Richard Helm, Ralph Johnson and John Vlissides.  That's a cool last
name, BTW.

[2] I'm new to XSLT (<2mo) and Relax NG (<1mo).

[3] Note that the entity:
 * &rng; should map to http://relaxng.org/ns/structure/1.0
 * &rwc; should map to
http://purl.org/jfc/2003/06/25/relax/ng/with/classes/

[4] http://purl.org/jfc/2003/06/26/test.xsl

[5] Note that some newlines were added by the email thing.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
  xmlns     = "http://relaxng.org/ns/structure/1.0"
  xmlns:rng = "http://relaxng.org/ns/structure/1.0"
  xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
  xmlns:c   = "http://purl.org/jfc/2003/06/25/relax/ng/with/classes/">
  <xsl:variable name="rngwc"
select="'http://purl.org/jfc/2003/06/25/relax/ng/with/classes/'" />


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


  <xsl:template match="/rng:grammar/c:class">
    <xsl:variable name="myName" select="@name" />
    <define name="{$myName}">
      <grammar>
        <xsl:apply-templates />
      </grammar>
    </define>
  </xsl:template>

  
  <xsl:template match="/rng:grammar/c:class/c:inherit">
    <xsl:variable name="myName" select="@name" />
    <xsl:variable name="myMom"  select=".." />
    
    <xsl:for-each select="/rng:grammar/c:class[@name =
$myName]/c:inherit">
      <xsl:apply-templates select="." />
    </xsl:for-each>
    
    <xsl:for-each select="/rng:grammar/c:class[@name =
$myName]/rng:define">
      <xsl:variable name="nameInContext" select="@name" />
      <xsl:if test="not($myMom/rng:define[@name=$nameInContext]) or
$myMom/rng:define[@name=$nameInContext][@combine]">
        <xsl:copy>
          <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
      </xsl:if>
    </xsl:for-each>
    
    <xsl:for-each select="/rng:grammar/c:class[@name =
$myName]/rng:start">
      <xsl:if test="not($myMom/rng:start) or
$myMom/rng:start[@combine]">
        <xsl:copy>
          <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
  

  <xsl:template match="node() | @*">
    <xsl:choose>
      <xsl:when test="(local-name(.)='inherit') and
(namespace-uri(.)=$rngwc)">
        <xsl:apply-templates select="@* | node()" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy>
          <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
 

Stylus Studio has published XML-DEV in RSS and ATOM formats, enabling users to easily subcribe to the list from their preferred news reader application.


Stylus Studio Sponsored Links are added links designed to provide related and additional information to the visitors of this website. they were not included by the author in the initial post. To view the content without the Sponsor Links please click here.

Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.