Eugeniy  Maksimov
Eugeniy Maksimov

Reputation: 1694

How to define XML element in xsd schema which can contain either one attribute or several others?

I use MVVM pattern in my project. I describe a view via XML. But I need to split it into several XML files because one XML file will be too large.

When my parser reads XML it find "Source" attribute first. If it exist the parser loads other XML document and reads element from this document. Else, if "Source" attribute does not exist parser reads other attributes.

Example with Source attribute:

<RibbonDefaultPageCategory>
  <RibbonPage
    Source="DefaultPageCategory/RibbonPage.xml"/>
</RibbonDefaultPageCategory> 

Example without Source attribute:

<RibbonDefaultPageCategory>
  <RibbonPage
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="_Schema.xsd"
    RibbonPageTitle="RibbonPageTitle">
     ...
   </RibbonPage>

Is it possible define this behavior in XML schema? Maybe it is possible use XML Element instead of attribute?

Like this

<ExternalElement
    ElementName="RibbonPage"
    Path="DefaultPageCategory/RibbonPage.xml"/> 

Upvotes: 1

Views: 552

Answers (2)

MiMo
MiMo

Reputation: 11953

It is not possible using attribute, but it is possible using elements. Something like this:

<xs:element name="RibbonPage">
  <xs:complexType>
    <xs:choice>
      <xs:element name="Source" type="xs:string"/>
      <xs:sequence>
        <xs:element name="RibbonPageTitle" type="xs:string"/>
        <!--
           ...place here the definiton of other elements defining the properties of 'RibbonPage'
        -->
      </xs:sequence>
    </xs:choice>
  </xs:complexType>
</xs:element>

validates either

<RibbonPage>
  <Source>...</Source>
</RibbonPage>

or

<RibbonPage>
  <RibbonPageTitle>...</RibbonPageTitle>

</RibbonPage>

but does not allow both Source and RibbonPageTitle at the same time.

An alternative is to use two different element names - e.g. RibbonPageRef when the definition is somewhere else and RibbonPage when the values are right in the element itself:

<xs:element name="RibbonDefaultPageCategory">
  <xs:complexType>
    <xs:choice>
      <xs:element name="RibbonPageRef">
        <xs:complexType>
          <xs:attribute name="Source" type="xs:string"/>
        </xs:complexType>
      </xs:element>
      <xs:element name="RibbonPage">
        <xs:complexType>
          <xs:attribute name="RibbonPageTitle" type="xs:string"/>
          <!--
             ...
          -->
        </xs:complexType>
      </xs:element>
    </xs:choice>
  </xs:complexType>
</xs:element>

in this way valid XML files are:

<RibbonDefaultPageCategory>
  <RibbonPageRef Source="..."/>
</RibbonDefaultPageCategory>

or

<RibbonDefaultPageCategory>
  <RibbonPage RibbonPageTitle="..."/>
</RibbonDefaultPageCategory>

Upvotes: 2

Michael Kay
Michael Kay

Reputation: 163302

People often overlook the possibility of doing transformations prior to schema validation. When you have a processing pipeline, it's often quite reasonable to have some kind of "normalization" step that precedes the validation step. The main disadvantage is that it will be harder to locate the cause of validation errors in terms of the source documents.

Upvotes: 0

Related Questions