XML Tutorials

  Home arrow XML Tutorials arrow Page 3 - Querying XML: Use Cases
XML TUTORIALS

Querying XML: Use Cases
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 3
    2008-02-14

    Table of Contents:
  • Querying XML: Use Cases
  • Use case SGML: Standard Generalized Markup Language.
  • Use case PARTS: recursive parts explosion.
  • Use case REF: queries based on references.
  • Further Discussion of the W3C XML Query-Use Cases in XSLT

  •  
     

    SEARCH CODEWALKERS

    TOOLS YOU CAN USE

    advertisement

    Querying XML: Use Cases - Use case PARTS: recursive parts explosion.


    (Page 3 of 5 )



    This use case illustrates how a recursive query might can construct a hierarchical document of arbitrary depth from flat structures stored in a database.

    This use case is based on a “parts explosion” database that contains information about how parts are used in other parts.

    The input to the use case is a “flat” document in which each different part is represented by a<part>element withpartidand name attributes. Each part may or may not be part of a larger part; if so, thepartidof the larger part is contained in apartof attribute. This input document might be derived from a relational
    database in which each part is represented by a table row withpartidas primary key andpartofas a foreign key referencingpartid.

    The challenge of this use case is to write a query that converts the “flat” representation of the parts explosion, based on foreign keys, into a hierarchical representation in which part containment is represented by the document structure.

    The input data set uses the following DTD:

      <!DOCTYPE partlist[
          <!ELEMENT partlist (part*)>
          <!ELEMENT part EMPTY>
          <!ATTLIST part
               partid   CDATA   #REQUIRED
               partof   CDATA   #IMPLIED
               name     CDATA   #REQUIRED>
      ]>

    Although thepartidandpartofattributes could have been of type ID and IDREF, respectively, in this schema they are treated as character data, possibly materialized in a straightforward way from a relational database. Eachpartofattribute matches exactly onepartid. Parts having nopartofattribute are not contained in any other part.

    The output data conforms to the following DTD:

      <!DOCTYPE parttree [
          <!ELEMENT parttree (part*)>
          <!ELEMENT part (part*)>
          <!ATTLIST part
                partid  CDATA  #REQUIRED
                name    CDATA  #REQUIRED>
      ]>

    Sample data conforming to that DTD might look like this:

      <?xml version="1.0" encoding="ISO-8859-1"?>
     
    <partlist>
        <part partid="0" name="car"/>
        <part partid="1" partof="0" name="engine"/>
        <part partid="2" partof="0" name="door"/>
        <part partid="3" partof="1" name="piston"/>
        <part partid="4" partof="2" name="window"/>
        <part partid="5" partof="2" name="lock"/>
        <part partid="10" name="skateboard"/>
        <part partid="11" partof="10" name="board"/>
        <part partid="12" partof="10" name="wheel"/>
        <part partid="20" name="canoe"/>

      </partlist>
    Question 1. Convert the sample document from "partlist" to "parttree" format (see
    the DTD section for definitions). In the result document, part containment is
    represented by containment of one <part> element inside another. Each part that
    is not part of any other part should appear as a separate top-level element in
    the output document:
    <xsl:template match="partlist">
      <parttree>
        <!-- Start with the part that is not part of anything -->
       <xsl:apply-templates select="part[not(@partof)]"/>
      </parttree>
    </xsl:template>

    <xsl:template match="part">
      <part partid="{@partid}" name="{@name}">
        <xsl:apply-templates select="../part[@partof = current()/@partid]"/>
      
    </part>
    </xsl:template>
    It turns out that this sort of transformation is easier to code and understand in
    XSLT than in XQuery. For comparison, here is the XQuery solution offered by the
    W3C paper:
    define function one_level (element $p) returns element
    {
      
    <part partid="{ $p/@partid }"
             name="{ $p/@name }" >
          
    {
              for $s in document("partlist.xml")//part
              where $s/@partof = $p/@partid
              return one_level($s)
          
    }
       </part>
    }

    <parttree>
     
    {
        for $p in document("partlist.xml")//part[empty(@partof)]
        return one_level($p)
     
    }
    </parttree>

    Even without a detailed understanding of XQuery, you should be able to see that the XQuery solution is needed to explicitly implement the recursion while XSLT’sapply-templatesand pattern matching allow a more declarative solution. Granted, the difference is not that dramatic, but I find XSLT more elegant for this type of problem.

    More XML Tutorials Articles
    More By O'Reilly Media

    blog comments powered by Disqus

    XML TUTORIALS ARTICLES

    - Validation with Document Type Definitions (D...
    - Creating a Well-Formed XML Document
    - Getting to Know XML
    - A Friendly Approach to XML
    - Creating RSS 2.0 Feeds
    - Using Modules in Your RSS Feed
    - RSS 2.0
    - Querying XML: Use Cases
    - Joins and Query Use with XML
    - Solving Problems by Querying XML
    - Performing Set Operations When Querying XML
    - Querying XML
    - Handling Data for Ajax with JSON
    - Handling XML Data for Ajax
    - XML and JSON for Ajax


    © 2003-2012 by Developer Shed. All rights reserved. DS Cluster 7 - Follow our Sitemap