Tim Clemons
Tim Clemons

Reputation: 6441

Finding XML attributes of a given type

Given a schema as follows:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://my.namespace/version/1" xmlns:tns="http://my.namespace/version/1" elementFormDefault="qualified">
  <xs:simpleType name="isbn">
    <xs:restriction base="xs:string">
      <xs:pattern value="(\d{10}|\d{13})"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="inventory">
    <xs:complexType>
      <xs:all>
        <xs:element ref="tns:cd"/>
        <xs:element ref="tns:book"/>
      </xs:all>
    </xs:complexType>
  </xs:element>

  <xs:element name="book">
    <xs:complexType>
      <xs:attribute name="id" use="required" type="tns:isbn"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="cd">
    <xs:complexType>
      <xs:attribute name="id" use="required" type="tns:isbn"/>
    </xs:complexType>  
  </xs:element>
</xs:schema>

And a corresponding XML file along the following:

<?xml version="1.0" encoding="utf-8"?>
<inventory xmlns="http://my.namespace/version/1">
  <book id="1000000000"/>
  <cd id="1234567891234"/>
</inventory>

Is there a way using XPath or some other query-based method of selecting all attributes of type isbn? Note that I don't want to query by the attribute name but rather the type as defined in the schema.

Upvotes: 0

Views: 44

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167571

To match or select based on a schema type you need to use schema aware XSLT 2.0 or later or schema-aware XQuery 1.0 or later where you make sure the schema is imported in XSLT or XQuery with a schema-aware processor like the Enterprise Edition EE of Saxon 9. Then you can use attribute(*, prefix:isbn) to select attributes based on the type.

A simple example is

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mns1="http://my.namespace/version/1" exclude-result-prefixes="xs mns1">

<xsl:import-schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://my.namespace/version/1" xmlns:tns="http://my.namespace/version/1" elementFormDefault="qualified">
  <xs:simpleType name="isbn">
    <xs:restriction base="xs:string">
      <xs:pattern value="(\d{10}|\d{13})"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="inventory">
    <xs:complexType>
      <xs:all>
        <xs:element ref="tns:cd"/>
        <xs:element ref="tns:book"/>
      </xs:all>
    </xs:complexType>
  </xs:element>

  <xs:element name="book">
    <xs:complexType>
      <xs:attribute name="id" use="required" type="tns:isbn"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="cd">
    <xs:complexType>
      <xs:attribute name="id" use="required" type="tns:isbn"/>
    </xs:complexType>  
  </xs:element>
</xs:schema>
</xsl:import-schema>


<xsl:template match="/">
    <xsl:variable name="ex1">
<inventory xmlns="http://my.namespace/version/1" xsl:validation="strict">
  <book id="1000000000"/>
  <cd id="1234567891234"/>
</inventory>
    </xsl:variable>

    <xsl:value-of select="$ex1//attribute(*, mns1:isbn)"/>

</xsl:template>
</xsl:transform>

online at http://xsltransform.net/nc4NzQF/1, to be tested with Saxon 9.5 EE.

It is meant to show how importing a schema works and how the attribute selection works, in real life you would want to use a validated input document instead of a variable content with a validated literal result element but I am not sure how to convince xsltransform.net to validate the input document, so the sample uses a result element instead of an input element.

Upvotes: 1

Related Questions