xsl-list
[Top] [All Lists]

RE: [xsl] How to check an element's type against an XSD simpleType and skip that element if it does not conform to the simpleType?

2013-07-16 07:08:19
Michael Kay wrote:

Unfortunately schema-aware processing in XQuery and XSLT 
doesn't give you this capability.

Is there a workaround?

Is there is no way for an XSLT program to express: "Hey, validate xyz against 
the XML Schema and if xyz is not schema-valid then discard it." No way to 
express that?

Here is an idea: feed into the XSLT program a BookStore XML document that is 
known to be schema-valid and then in the XSLT program ignore it and instead 
process BookStore-v2.xml, which is input via the document() function. Below is 
my attempt at this. I no longer get an error, but it doesn't give the correct 
results; it just gives an empty root element (<BookISBNs/> ) Any suggestions?

---------------------------------------------------------------
     Roger's Brilliant Workaround BookStore.xsl
             (doesn't work as desired)
---------------------------------------------------------------
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
               xmlns:bk="http://www.books.org";
               exclude-result-prefixes="bk"
               version="2.0">
 
    <xsl:output method="xml"/>
    
    <xsl:variable name="new-BookStore" select="document('BookStore-v2.xml')" />

    <xsl:import-schema namespace="http://www.books.org";
        schema-location="BookStore.xsd"/>
    
    <xsl:template match="/">
        <BookISBNs>
            <xsl:for-each 
select="$new-BookStore/bk:BookStore/bk:Book/bk:ISBN/text()">
                <xsl:if test=". instance of bk:ISBN-type">
                    <ISBN><xsl:value-of select="."/></ISBN>
                </xsl:if>
            </xsl:for-each>
        </BookISBNs>
    </xsl:template>

</xsl:transform>


-----Original Message-----
From: Michael Kay [mailto:mike(_at_)saxonica(_dot_)com] 
Sent: Tuesday, July 16, 2013 5:49 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] How to check an element's type against an XSD simpleType and 
skip that element if it does not conform to the simpleType?

Unfortunately schema-aware processing in XQuery and XSLT doesn't give you this 
capability. XSLT doesn't have the capability to process a PSVI that contains a 
mix of valid and marked-as-invalid elements. It would be nice if it did, and 
perhaps that's something for me to explore as a Saxon extension.

Michael Kay
Saxonica


On 15 Jul 2013, at 19:55, Costello, Roger L. wrote:

Hi Folks,

I would like to do schema-aware processing on this document:

<BookStore xmlns="http://www.books.org";>
       <Book>
               <Title>My Life and Times</Title>
               <Author>Paul McCartney</Author>
               <Date>1998</Date>
               <ISBN>xxx1-56592-235-2</ISBN>
               <Publisher>McMillan Publishing</Publisher>
       </Book>
       ...
</BookStore>

I have a corresponding XML Schema, which I show in its entirety at the bottom 
of this message. The item of interest, however, is its simpleType for ISBN 
elements: 

   <xsd:simpleType name="ISBN-type">
       <xsd:restriction base="xsd:string">
           <xsd:pattern 
value="\d{1}-\d{5}-\d{3}-\d{1}|\d{1}-\d{3}-\d{5}-\d{1}|\d{1}-\d{2}-\d{6}-\d{1}"/>
           
       </xsd:restriction>
   </xsd:simpleType>

I want my XSLT program to output each ISBN in the XML document. If an ISBN 
does not conform to the simpleType, then I want to skip that ISBN element and 
continue processing. At the bottom of this message is the XSLT in its 
entirety. The item of interest, however, is this snippet:

           <xsl:for-each select="/bk:BookStore/bk:Book">
               <xsl:if test="data(bk:ISBN) instance of bk:ISBN-type">
                   <ISBN><xsl:value-of select="bk:ISBN"/></ISBN>
               </xsl:if>
           </xsl:for-each>

The for-loop iterates through each Book and checks to see if the value of its 
ISBN element conforms to ISBN-type; if it doesn't conform, then it skips that 
ISBN and goes to the next Book.

In the XML document shown above, the Book element has an ISBN 
(xxx1-56592-235-2) that is not valid, so I expect my XSLT program to skip it.

However, that is not happening. I get this error message:

   The content "xxx1-56592-235-2" of element <ISBN> does not 
   match the required simple type. Value "xxx1-56592-235-2" 
   contravenes the pattern facet "\d{1}-\d{5}-\d{3}-\d{1}|\d{1}-..." 
   of the type ISBN-type

What am I doing wrong please?

/Roger
-----------------------------------------------------------
      BookStore.xsl
-----------------------------------------------------------
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
              xmlns:bk="http://www.books.org";
              exclude-result-prefixes="bk"
              version="2.0">

   <xsl:output method="xml"/>

   <xsl:import-schema namespace="http://www.books.org";
                      schema-location="BookStore.xsd"/>

   <xsl:template match="/">
       <BookISBNs>
           <xsl:for-each select="/bk:BookStore/bk:Book">
               <xsl:if test="data(bk:ISBN) instance of bk:ISBN-type">
                   <ISBN><xsl:value-of select="bk:ISBN"/></ISBN>
               </xsl:if>
           </xsl:for-each>
       </BookISBNs>
   </xsl:template>

</xsl:transform>

-----------------------------------------------------------
      BookStore.xsd
-----------------------------------------------------------
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema";
           targetNamespace="http://www.books.org";
           xmlns="http://www.books.org";
           elementFormDefault="qualified">

   <xsd:element name="BookStore">
       <xsd:complexType>
           <xsd:sequence>
               <xsd:element ref="Book" minOccurs="0" maxOccurs="unbounded"/>
           </xsd:sequence>
       </xsd:complexType>
   </xsd:element>

   <xsd:element name="Book">
       <xsd:complexType>
           <xsd:sequence>
               <xsd:element ref="Title"/>
               <xsd:element ref="Author"/>
               <xsd:element ref="Date"/>
               <xsd:element ref="ISBN"/>
               <xsd:element ref="Publisher"/>
           </xsd:sequence>
       </xsd:complexType>
   </xsd:element>

   <xsd:element name="Title" type="xsd:string"/>
   <xsd:element name="Author" type="xsd:string"/>
   <xsd:element name="Date" type="xsd:string"/>
   <xsd:element name="ISBN" type="ISBN-type"/>
   <xsd:element name="Publisher" type="xsd:string"/>

   <xsd:simpleType name="ISBN-type">
       <xsd:restriction base="xsd:string">
           <xsd:pattern 
value="\d{1}-\d{5}-\d{3}-\d{1}|\d{1}-\d{3}-\d{5}-\d{1}|\d{1}-\d{2}-\d{6}-\d{1}"/>
           
       </xsd:restriction>
   </xsd:simpleType>

</xsd:schema>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--


<Prev in Thread] Current Thread [Next in Thread>