Search code examples
xmlxsdxsd-validationxercesxerces-c

work around for validating XML child elements


Basically my question is whether or not there is way to validate a non-root element according to a given XSD schema.

I am currently working on some legacy code where we have some C++ classes that generate XML elements in string format.

I was thinking about a way to unit test these classes by verifying the generated XML (I'm using Xerces C++ under the hood). The problem is that I can't reference an element from another schema different from the root.

This is a more detailed description of what I'm doing:

I have a class called BooGenerator that generates a 'booIsNotRoot' element defined in 'foo.xsd'. Note that 'boo' is not the root element :-)

I have created a test.xsd schema, which references 'booIsNotRoot' in the following way:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://acme/2014/test"
            xmlns:foo="http://acme/2014/foo"
            targetNamespace="http://acme/2014/test"
            elementFormDefault="qualified">
  <xsd:import namespace="http://acme/2014/foo" schemaLocation="foo.xsd"/>
  <xsd:complexType name="TestType">
    <xsd:choice minOccurs="1" maxOccurs="1">
      <xsd:element ref="foo:booIsNotRoot"/>
    </xsd:choice>
  </xsd:complexType>
  <xsd:element name="test" type="TestType"/>
</xsd:schema>

Then I wrap the string generated by BooGenerator with a test element:

<test xmlns="xmlns="http://acme/2014/test"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:foo="http://acme/2014/foo
      xsi:schemaLocation="http://acme/2014/test test.xsd">
  (code generated by BooGenerator prefixed with 'foo')
</test>

but as I said before it doesn't work. If I reference the root element in foo.xsd it works. So I wonder if there is a way to work around this.

Thanks in advance.


Solution

  • Basically my question is whether or not there is way to validate a non-root 
    element according to a given XSD schema.
    

    Theoretically speaking, yes, Section 5.2 Assessing Schema-Validity of the XSD Recommendation allows for non-root element validity assessment. (Credit and thanks to C. M. Sperberg-McQueen for pointing this out.)

    Practically speaking, no, not directly. XML Schema tools tend to validate against XML documents — not selected, individual elements — and XML documents must have a single root element. Perhaps you might embed the element you wish to validate within a rigged context that simulates the element's ancestry up to the proper root element for the document.

    If I reference the root element in foo.xsd it works.

    The root element in foo.xsd had better be xsd:schema, actually. You probably mean to say

    If I reference an element defined globally (under xsd:schema) in foo.xsd it works.

    That is also how @ref is defined to work in XML Schema — it cannot reference locally defined elements such as foo:booIsNotRoot. Furthermore, any globally defined element can serve as a root element. (In fact, only globally defined elements can serve as a root element.)

    So, your options include:

    1. Rig a valid context in which to test your targeted element.
    2. Make your targeted element globally defined in its XSD.
    3. Identify an implementation-specific interface to your XSD validator that provides element-level validation.