xmlxsdxquerymarklogicmarklogic-8

Xquery to get attribute name and type from a XSD schema?


I was following a tutorial from marklogic,

https://developer.marklogic.com/learn/2007-04-schema

In a scenario, where I have xsd file

    <!-- tutorial.xsd -->
<xs:schema targetNamespace="http://marklogic.com/tutorial"
 attributeFormDefault="unqualified"
 elementFormDefault="unqualified"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="name" type="xs:token"
   abstract="false" nillable="false"/>
  <xs:element name="qualification" type="xs:token"
   abstract="false" nillable="false"/>
  <xs:element name="born" type="xs:date"
   abstract="false" nillable="false"/>
  <xs:element name="dead" type="xs:date"
   abstract="false" nillable="false"/>
  <xs:element name="isbn" type="xs:unsignedLong"
   abstract="false" nillable="false"/>
  <xs:attribute name="id" type="xs:ID"/>
  <xs:attribute name="available" type="xs:boolean"/>
  <xs:attribute name="lang" type="xs:language"/>
  <xs:element name="title" abstract="false" nillable="false">
    <xs:complexType mixed="false">
      <xs:simpleContent>
    <xs:extension base="xs:token">
      <xs:attribute ref="lang" use="optional"/>
    </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:element name="library" abstract="false" nillable="false">
    <xs:complexType mixed="false">
      <xs:sequence minOccurs="1" maxOccurs="1">
    <xs:element ref="book" maxOccurs="unbounded" minOccurs="1"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="author" abstract="false" nillable="false">
    <xs:complexType mixed="false">
      <xs:sequence minOccurs="1" maxOccurs="1">
    <xs:element ref="name" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="born" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="dead" minOccurs="0" maxOccurs="1"/>
      </xs:sequence>
      <xs:attribute ref="id" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="book" abstract="false" nillable="false">
    <xs:complexType mixed="false">
      <xs:sequence minOccurs="1" maxOccurs="1">
    <xs:element ref="isbn" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="title" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="author" minOccurs="0"
   maxOccurs="unbounded"/>
    <xs:element ref="character" minOccurs="0"
   maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute ref="id" use="optional"/>
      <xs:attribute ref="available" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="character" abstract="false" nillable="false">
    <xs:complexType mixed="false">
      <xs:sequence minOccurs="1" maxOccurs="1">
    <xs:element ref="name" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="born" minOccurs="1" maxOccurs="1"/>
    <xs:element ref="qualification" minOccurs="1"
   maxOccurs="1"/>
      </xs:sequence>
      <xs:attribute ref="id" use="optional"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

I wanted to extract the attribute name and type from this xsd. Following is my XQuery:

if (xdmp:database-name(xdmp:database()) ne 'Schemas')
then error(
  QName('', 'NOT-SCHEMAS'), 'make sure the content-source is Schemas')
else
doc('tutorial.xsd')
  /descendant::xs:element/@name
(: results :)

I am getting the following:

name
qualification
born
dead
isbn
title
library
author
book
character

but I need the attribute and the value together

name xs:token
qualification xs:token
born xs:token

Can someone help me rewrite the Xquery to achive this above output?


Solution

  • You just need to loop through the elements, then get the attributes for each. In the return statement below, you can combine them into a string, put them into a map, or whatever you need to do with them.

    if (xdmp:database-name(xdmp:database()) ne 'Schemas') then 
      error(
        QName('', 'NOT-SCHEMAS'), 'make sure the content-source is Schemas')
    else
      for $element in doc('tutorial.xsd')/descendant::xs:element
      where $element/@name and $element/@type
      return $element/@name || " is a " || $element/@type
    

    The where clause requires both the name and type attributes to be present. You can change it to an or to get either of them, or you just require $element/@name if you want all names, event when types are not present.