xsl-list
[Top] [All Lists]

Re: re-ordering an instance to match a schema

2003-05-15 09:55:03
Hi Simon,

Okay, cool.

I'm going to break the problem into two pieces and discuss them separately. This is because I think you have two problems, one you asked about, and one which you've made some indications of (my questions of yesterday), but which remains underspecified.

The second problem is "how do I transform an arbitrary RNG schema to get the ("author-implied") order of elements allowed as children of a given element". Not only is this a tricky question in the general case, but it's also possible to stipulate you've got a solution. So let's jump ahead and say you've already transformed your schema, boiling it down to a representation of your desired order. Given source like yours:

<element name="contact">
  <zeroOrMore>
    <choice>
      <element name="phone">
        <optional>
          <attribute name="location">
            <choice>
              <value>
                home
              </value>
              <value>
                work
              </value>
              <value>
                mobile
              </value>
            </choice>
          </attribute>
        </optional>
        <text />
      </element>
      <element name="fax">
        <optional>
          <attribute name="location">
            <choice>
              <value>
                home
              </value>
              <value>
                work
              </value>
            </choice>
          </attribute>
        </optional>
        <text />
      </element>
      <element name="pager">
        <text />
      </element>
      <element name="email">
        <text />
      </element>
      <element name="url">
        <text />
      </element>
      <element name="instantMessage">
        <optional>
          <attribute name="service" />
        </optional>
        <text />
      </element>
    </choice>
  </zeroOrMore>
</element>

Let's say you can transform this to represent the order you want as:

<elementdecl name="contact">
  <element name="phone"/>
  <element name="fax"/>
  <element name="pager"/>
  <element name="email"/>
  <element name="url"/>
  <element name="instantMessage"/>
</elementdecl>

(This transform shouldn't be too hard to write, eh?)

The reason to reconceive the problem this way is that by dumping everything the schema says about what's optional, wrapped in <zeroOrMore>, etc. etc., we simplify down to just what we need, namely the order we want these elements are to appear in, assuming they appear. (Note we're not interested in validating anything, only in knowing how to rearrange things.)

Let's name this XML "elementorder.xml".

Your source looks like:

<contact>
  <url>http://www.simonwoodside.com/<url>
  <email>sbwoodside(_at_)yahoo(_dot_)com</email>
  <phone location="work">555-1212</phone>
  <fax>555-1111</fax>
</contact>

And what you want to do:

<xsl:template match="*">
  <xsl:variable name="thisNode" select="."/>
  <!-- we'll need our matched node after we change context -->
<xsl:variable name="orderNode" select="document('elementorder.xml')//elementdecl[(_at_)name=local-name(current())]"/> <!-- this variable is a convenience for clarity: finds the node corresponding to the
       declaration of thisNode (the same as current(), here) -->
  <xsl:for-each select="$orderNode/*">
    <!-- we iterate over the child elements declared for $orderNode -->
    <xsl:variable name="orderedNode" select="."/>
    <!-- the child is bound to another variable -->
    <xsl:copy-of select="$thisNode/*[local-name()=$orderedNode/@name]"/>
    <!-- into our result we copy all the children of $thisNode whose name
         equals the @name on $orderedNode -->
  </xsl:for-each>
</xsl:template>

I hope that's enough to get across the idea. Basically we're using the document order of the lookup table (the boiled-down schema) to drive the ordering of the nodes copied into the result. The variables allow us access to the nodes in both source trees as we change context.

Good luck!
Wendell

___&&__&_&___&_&__&&&__&_&__&__&&____&&_&___&__&_&&_____&__&__&&_____&_&&_
    "Thus I make my own use of the telegraph, without consulting
     the directors, like the sparrows, which I perceive use it
     extensively for a perch." -- Thoreau


XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list