Jeroen Wiert Pluimers
Jeroen Wiert Pluimers

Reputation: 24513

Validating a nested XML element with an empty namespace using XSD

I'm trying to validate a bunch XML file that looks roughly like this (an example full file is at Gist):

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- ... -->
  <ProjectExtensions>
    <Borland.Personality>Default.Personality</Borland.Personality>
    <Borland.ProjectType />
    <BorlandProject>
  <BorlandProject xmlns=""> <Default.Personality> </Default.Personality> </BorlandProject></BorlandProject>
  </ProjectExtensions>
  <!-- ... -->
</Project>

I know the nested <BorlandProject xmlns=""> is odd, but a lot of those XML files in our repository are that way and I want to validate them OK.

The files use a subset of the MSBuild definition. So far I've tried something like this (again: full file in on Gist):

<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0"
  targetNamespace="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Project" type="ProjectType"/>
  <!-- ... -->
  <xsd:complexType name="ProjectExtensionsType">
    <xsd:sequence>
      <xsd:element name="Borland.Personality" type="xsd:string"/>
      <xsd:element name="Borland.ProjectType" type="xsd:string"/>
      <xsd:element name="BorlandProject" type="BorlandProjectType"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="BorlandProjectType">
    <xsd:choice>
      <xsd:sequence>
        <xsd:element name="Default.Personality" type="xsd:string"/>
      </xsd:sequence>
      <xsd:element name="BorlandProject" type="BorlandProjectType"/>
    </xsd:choice>
  </xsd:complexType>
  <!-- ... -->
</xsd:schema>

Validating barfs with an error message like this:

Error: The element 'BorlandProject' in namespace 'http://schemas.microsoft.com/developer/msbuild/2003'  
has invalid child element 'BorlandProject'.  
List of possible elements expected:   
'Default.Personality, BorlandProject' in namespace 'http://schemas.microsoft.com/developer/msbuild/2003'.  
<BorlandProject>

I think this is because of the odd xmlns="" inside <BorlandProject xmlns="">.

Two questions:

  1. Is my xmlns="" assumption right?
  2. How can I validate this <BorlandProject xmlns=""> element?

Edit

Thanks ColdFusion for his answer. This is what I finally did, as the BorlandProject can both be qualified and unqualified:

  <xsd:complexType name="BorlandProjectType">
    <xsd:choice>
      <xsd:sequence>
        <xsd:element name="Default.Personality" type="xsd:string"/>
      </xsd:sequence>
      <!-- Delphi <= 2010 can have a nested `BorlandProject` element, sometimes unqualified (with xmlns=""), sometimes qualified -->
      <xsd:choice>
        <xsd:element name="BorlandProject" form="unqualified" type="BorlandProjectTypeUnqualified"/>
        <xsd:element name="BorlandProject" type="BorlandProjectTypeQualified"/>
      </xsd:choice>
    </xsd:choice>
  </xsd:complexType>
  <xsd:complexType name="BorlandProjectTypeUnqualified">
    <xsd:sequence>
      <xsd:element name="Default.Personality" form="unqualified" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="BorlandProjectTypeQualified">
    <xsd:sequence>
      <xsd:element name="Default.Personality" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>

Upvotes: 0

Views: 1736

Answers (2)

Dijkgraaf
Dijkgraaf

Reputation: 11527

  1. Yes, after removing the xmlns="" the XML validates.

  2. a) The simplest solution would be to remove the invalid xmlns from the XML.

    b) Harder would be to have another schema which you import that has no namespace that defines another the BorlantProjectType which you can reference. I tried this and couldn't get it to work.

    c) Another possibility is to generate a new schema based on the XML and then validate against that. I did that and then tweaked it a bit the get the nesting in the include happening. However as this was just tested against one sample it may need some more tweaking. XSDs here https://gist.github.com/anonymous/6408209 & https://gist.github.com/Dijkgraaf/6408223

EDIT: d) Go with the answer ColdFusion gave which is a lot simpler.

Upvotes: 1

ColdFusion
ColdFusion

Reputation: 2531

Is my xmlns="" assumption right?

Yes. Having xmlns="" is nothing wrong. The "" is also a namespace -- the global one (or "nonamespace").

How can I validate this element?

The elements in nonamespace are called unqualified.

As long as all elements, which you need to be unqualified, are local ones (that is nested in some other elements), that can be specifically declared (for each particular element) using form="unqualified" attribute.

Note: Whether all local elements (defined in the schema) are qualified or not is specified with elementFormDefault attribute in <xsd:schema>. But you can mix it, so as to have some local elements qualified and some not.

For instance, your XML file (provided in your question) can be validated against this schema:

<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
  version="1.0"
  targetNamespace="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:element name="Project" type="ProjectType"/>

  <xsd:complexType name="ProjectType">
    <xsd:sequence>
      <xsd:element name="ProjectExtensions" type="ProjectExtensionsType"/>
    </xsd:sequence>
  </xsd:complexType>

  <!-- ... -->
  <xsd:complexType name="ProjectExtensionsType">
    <xsd:sequence>
      <xsd:element name="Borland.Personality" type="xsd:string"/>
      <xsd:element name="Borland.ProjectType" type="xsd:string"/>
      <xsd:element name="BorlandProject" type="BorlandProjectType"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="BorlandProjectType">
    <xsd:choice>
      <xsd:sequence>
        <xsd:element name="Default.Personality" type="xsd:string"
                     form="unqualified"/>
      </xsd:sequence>
      <xsd:element name="BorlandProject" type="BorlandProjectType"
                   form="unqualified"/>
    </xsd:choice>
  </xsd:complexType>
  <!-- ... -->
</xsd:schema>

Note that according to that schema you actually have two BorlandProject elements: one in http://schemas.microsoft.com/developer/msbuild/2003 and another one in no namespace. I don't know, whether you really need this... But that's how your XML is written.

Upvotes: 4

Related Questions