Search code examples
xmlxsdxml-namespacesxsd-validationxml-validation

XSD to validate namespaced attributes on non-namespaced elements?


I have been asked to create schemas for validating documents whose structures were developed before XML Schema became a thing. None of the elements have a colon in the name, but some of the attributes do. It seems that in theory it should be possible to do it with something like this:

$ cat repro.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="" xmlns:x="namespace-x" targetNamespace="">
 <xsd:import namespace="namespace-x" schemaLocation="repro.inc"/>
 <xsd:element name="a" type="a"/>
 <xsd:complexType name="a">
  <xsd:simpleContent>
   <xsd:extension base="xsd:string">
    <xsd:attribute ref="x:y"/>
   </xsd:extension>
  </xsd:simpleContent>
 </xsd:complexType>
</xsd:schema>
$ cat repro.inc
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="namespace-x">
 <xsd:attribute name="y" type="xsd:string"/>
</xsd:schema>

But the schema validator complains:

$ cat repro.xml
<a xmlns:x="namespace-x" x:y="foo"/>
$ xmllint --schema repro.xsd repro.xml
<?xml version="1.0"?>
<a xmlns:x="namespace-x" x:y="foo"/>
repro.xml:1: element a: Schemas validity error : Element 'a': No matching global declaration available for the validation root.
repro.xml fails to validate

Doesn't targetNamespace="" mean the elements defined in this schema document don't use a namespace? If not, how does one go about validating such documents using XML Schema?

Unfortunately, putting the elements in a namespace without a prefix (xmlns="other-ns") would break a very large quantity of software which uses namespace-aware parsers, so a solution along those lines is unappealing.


Solution

  • Doesn't targetNamespace="" mean the elements defined in this schema document don't use a namespace? If not, how does one go about validating such documents using XML Schema?

    No, the value of targetNamespace must never be empty; simply omit targetNamespace for no namespace instead. You can also remove xmlns="" from xsd:schema.

    repro.xsd

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:x="namespace-x">
      <xsd:import namespace="namespace-x" schemaLocation="repro.inc"/>
      <xsd:element name="a" type="a"/>
      <xsd:complexType name="a">
        <xsd:simpleContent>
          <xsd:extension base="xsd:string">
            <xsd:attribute ref="x:y"/>
          </xsd:extension>
        </xsd:simpleContent>
      </xsd:complexType>
    </xsd:schema>
    

    repro.inc and repro.xml are fine as they are.

    With the above changes, your XSD will validate your XML successfully.