XML.orgXML.org
FOCUS AREAS |XML-DEV |XML.org DAILY NEWSLINK |REGISTRY |RESOURCES |ABOUT
OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]
RE: Got a program that generates a list of assertions about an XSD?

Hi Folks,

So, today I spent a few minutes writing an XSLT program that turns an XML Schema into a list of simple assertions.

For this XML Schema:
-------------------------------------------------------------
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
            	      targetNamespace="http://www.books.org";
            	      xmlns="http://www.books.org";
           	      elementFormDefault="qualified">
    
    <xs:element name="BookStore">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Book" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="Title" type="xs:string"/>
                            <xs:element name="Author" type="xs:string"/>
                            <xs:element name="Date" type="xs:gYear"/>
                            <xs:element name="ISBN" type="xs:string"/>
                            <xs:element name="Publisher" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>
-------------------------------------------------------------

my XSLT program generates this list of assertions:

        (BookStore file Book-Store.xsd)
        (BookStore kind element)
        (BookStore targetNamespace "http://www.books.org";)
        (BookStore type complexType)
        (BookStore minOccurs 1)
        (BookStore maxOccurs 1)
        (BookStore default none)
        (BookStore fixed none)
        (BookStore parent schema)
        (BookStore location /schema/element[BookStore])
        (Book file Book-Store.xsd)
        (Book kind element)
        (Book targetNamespace "http://www.books.org";)
        (Book type complexType)
        (Book minOccurs 1)
        (Book maxOccurs unbounded)
        (Book default none)
        (Book fixed none)
        (Book parent BookStore)
        (Book location /schema/element[BookStore]/complexType/sequence/element[Book])
        (Title file Book-Store.xsd)
        (Title kind element)
        (Title targetNamespace "http://www.books.org";)
        (Title type string)
        (Title minOccurs 1)
        (Title maxOccurs 1)
        (Title default none)
        (Title fixed none)
        (Title parent Book)
        (Title location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Title])
        (Author file Book-Store.xsd)
        (Author kind element)
        (Author targetNamespace "http://www.books.org";)
        (Author type string)
        (Author minOccurs 1)
        (Author maxOccurs 1)
        (Author default none)
        (Author fixed none)
        (Author parent Book)
        (Author location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Author])
        (Date file Book-Store.xsd)
        (Date kind element)
        (Date targetNamespace "http://www.books.org";)
        (Date type gYear)
        (Date minOccurs 1)
        (Date maxOccurs 1)
        (Date default none)
        (Date fixed none)
        (Date parent Book)
        (Date location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Date])
        (ISBN file Book-Store.xsd)
        (ISBN kind element)
        (ISBN targetNamespace "http://www.books.org";)
        (ISBN type string)
        (ISBN minOccurs 1)
        (ISBN maxOccurs 1)
        (ISBN default none)
        (ISBN fixed none)
        (ISBN parent Book)
        (ISBN location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[ISBN])
        (Publisher file Book-Store.xsd)
        (Publisher kind element)
        (Publisher targetNamespace "http://www.books.org";)
        (Publisher type string)
        (Publisher minOccurs 1)
        (Publisher maxOccurs 1)
        (Publisher default none)
        (Publisher fixed none)
        (Publisher parent Book)
        (Publisher location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Publisher])
 
Then I used a pattern matcher (expressed in Common Lisp) to search the list of assertions for answers to questions:
-------------------------------------------------------
Question: What items have type string?

Query: (fetch '(? type string))

Results: ((TITLE TYPE STRING) 
	 (AUTHOR TYPE STRING) 
	 (ISBN TYPE STRING)
 	 (PUBLISHER TYPE STRING))
-------------------------------------------------------
Question: What are the children of Book?

Query: (mapcar #'first (fetch '(? parent Book)))

Answer: (TITLE AUTHOR DATE ISBN PUBLISHER)
-------------------------------------------------------
Question: What elements have unbounded occurrences?

Query: (fetch '(? maxOccurs unbounded))

Answer: ((BOOK MAXOCCURS UNBOUNDED))
-------------------------------------------------------
Question: What are the potential root elements?

Query: (mapcar #'first (fetch '(? parent schema)))

Answer: (BOOKSTORE)
-------------------------------------------------------

Those are probing the schema with simple questions and queries, but the kinds of questions and queries that are possible are limited only by one's imagination.

This is pretty cool: using simple assertions about a schema to get answers to complex questions.

I think that "list of assertions" might be a useful common intermediate format for both XML Schema and JSON Schema. Your thoughts on this?

Below is the XSLT program that I wrote to generate the list of assertions, followed by the Common Lisp pattern matcher program that I wrote.

--------------------------------------------------------------
 XSLT Program to Generate a List of Assertions
--------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    	xmlns:xs="http://www.w3.org/2001/XMLSchema";
    	xmlns:f="functions"
    	exclude-result-prefixes="xs f"
    	version="2.0">
    
    <xsl:output method="text" />
    
    <xsl:variable name="tns" select="/xs:schema/@targetNamespace"/>
    
    <xsl:template match="/">
        <xsl:text>(setf database
      '(</xsl:text>
        <xsl:for-each select="//xs:element[@name]">
            <xsl:apply-templates select="." />
            <xsl:text>
        </xsl:text>
        </xsl:for-each>
        <xsl:text>))</xsl:text>
    </xsl:template>
    
    <xsl:template match="xs:element[@name]">
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> file Book-Store.xsd)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> kind element)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> targetNamespace "</xsl:text><xsl:value-of select="$tns"/><xsl:text>")</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> type </xsl:text><xsl:value-of select="f:my-type(.)"/><xsl:text>)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> minOccurs </xsl:text><xsl:value-of select="if (not (@minOccurs)) then 1 else @minOccurs"/><xsl:text>)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> maxOccurs </xsl:text><xsl:value-of select="if (not (@maxOccurs)) then 1 else @maxOccurs"/><xsl:text>)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> default </xsl:text><xsl:value-of select="if (not (@default)) then 'none' else @default"/><xsl:text>)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> fixed </xsl:text><xsl:value-of select="if (not (@fixed)) then 'none' else @fixes"/><xsl:text>)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> parent </xsl:text><xsl:value-of select="f:my-parent(.)"/><xsl:text>)</xsl:text>
        <xsl:text>
        </xsl:text>
        <xsl:text>(</xsl:text><xsl:value-of select="@name"/><xsl:text> location </xsl:text><xsl:value-of select="f:XPath-to-item(.)"/><xsl:text>)</xsl:text>
    </xsl:template>
    
    <xsl:function name="f:my-type">
        <xsl:param name="element" />
        
        <xsl:choose>
            <xsl:when test="$element[@type]"><xsl:value-of select="if (contains($element/@type, ':')) then substring-after($element/@type, ':') else $element/@type" /></xsl:when>
            <xsl:when test="$element[child::xs:complexType]"><xsl:text>complexType</xsl:text></xsl:when>
            <xsl:when test="$element[child::xs:simpleType]"><xsl:text>simpleType</xsl:text></xsl:when>
        </xsl:choose>
    </xsl:function>
    
    <xsl:function name="f:my-parent">
        <xsl:param name="element" />
        
        <xsl:value-of select="f:my-parent-aux($element/..)"/>
    </xsl:function>
    
    <xsl:function name="f:my-parent-aux">
        <xsl:param name="node" />
        
        <xsl:choose>
            <xsl:when test="$node[self::xs:element[@name]]"><xsl:value-of select="$node/@name" /></xsl:when>
            <xsl:when test="$node[self::xs:complexType[@name]]"><xsl:value-of select="$node/@name" /></xsl:when>
            <xsl:when test="$node[self::xs:schema]">schema</xsl:when>
            <xsl:otherwise><xsl:value-of select="f:my-parent-aux($node/..)"/></xsl:otherwise>
        </xsl:choose>
    </xsl:function>
    
    <xsl:function name="f:XPath-to-item">
        <xsl:param name="item" as="element()" />  
        
        <xsl:for-each select="$item/ancestor-or-self::*">
            <xsl:text>/</xsl:text>
            <xsl:value-of select="local-name()"/>
            <xsl:variable name="name" select="local-name()"/>
            <xsl:choose>
                <xsl:when test="@name">
                    <xsl:text>[</xsl:text><xsl:value-of select="@name"/><xsl:text>]</xsl:text>
                </xsl:when>
                <xsl:when test="@ref">
                    <xsl:text>[</xsl:text><xsl:value-of select="@ref"/><xsl:text>]</xsl:text>
                </xsl:when>
                <xsl:when test="count(preceding-sibling::*[local-name() = $name]) &gt; 0">
                    <xsl:text>[</xsl:text><xsl:value-of select="count(preceding-sibling::*[local-name() = $name]) + 1"/><xsl:text>]</xsl:text>
                </xsl:when>
            </xsl:choose>
        </xsl:for-each>    
    </xsl:function>
</xsl:stylesheet>

--------------------------------------------------------------
     Common Lisp Pattern Matcher Program
--------------------------------------------------------------
(setf database
      '((BookStore file Book-Store-v1.xsd)
        (BookStore kind element)
        (BookStore targetNamespace "http://www.books.org";)
        (BookStore type complexType)
        (BookStore minOccurs 1)
        (BookStore maxOccurs 1)
        (BookStore default none)
        (BookStore fixed none)
        (BookStore parent schema)
        (BookStore location /schema/element[BookStore])
        (Book file Book-Store-v1.xsd)
        (Book kind element)
        (Book targetNamespace "http://www.books.org";)
        (Book type complexType)
        (Book minOccurs 1)
        (Book maxOccurs unbounded)
        (Book default none)
        (Book fixed none)
        (Book parent BookStore)
        (Book location /schema/element[BookStore]/complexType/sequence/element[Book])
        (Title file Book-Store-v1.xsd)
        (Title kind element)
        (Title targetNamespace "http://www.books.org";)
        (Title type string)
        (Title minOccurs 1)
        (Title maxOccurs 1)
        (Title default none)
        (Title fixed none)
        (Title parent Book)
        (Title location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Title])
        (Author file Book-Store-v1.xsd)
        (Author kind element)
        (Author targetNamespace "http://www.books.org";)
        (Author type string)
        (Author minOccurs 1)
        (Author maxOccurs 1)
        (Author default none)
        (Author fixed none)
        (Author parent Book)
        (Author location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Author])
        (Date file Book-Store-v1.xsd)
        (Date kind element)
        (Date targetNamespace "http://www.books.org";)
        (Date type gYear)
        (Date minOccurs 1)
        (Date maxOccurs 1)
        (Date default none)
        (Date fixed none)
        (Date parent Book)
        (Date location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Date])
        (ISBN file Book-Store-v1.xsd)
        (ISBN kind element)
        (ISBN targetNamespace "http://www.books.org";)
        (ISBN type string)
        (ISBN minOccurs 1)
        (ISBN maxOccurs 1)
        (ISBN default none)
        (ISBN fixed none)
        (ISBN parent Book)
        (ISBN location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[ISBN])
        (Publisher file Book-Store-v1.xsd)
        (Publisher kind element)
        (Publisher targetNamespace "http://www.books.org";)
        (Publisher type string)
        (Publisher minOccurs 1)
        (Publisher maxOccurs 1)
        (Publisher default none)
        (Publisher fixed none)
        (Publisher parent Book)
        (Publisher location /schema/element[BookStore]/complexType/sequence/element[Book]/complexType/sequence/element[Publisher])
        ))
		
(defun match-element (symbol1 symbol2)
    (cond ((equal symbol1 symbol2) t)
	((equal symbol2 '?) t)
        	(t nil)))
		  
(defun match-triple (assertion pattern)
    (and 	(= (length assertion) (length pattern))
            	(= (length assertion) 3)
            	(match-element (first assertion) (first pattern))
	(match-element (second assertion) (second pattern))
	(match-element (third assertion) (third pattern))))

(defun fetch (pattern)
    (remove nil (mapcar #'(lambda (assertion) (if (match-triple assertion pattern) assertion)) database)))


[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]


News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 1993-2007 XML.org. This site is hosted by OASIS