title: XSD 1.1 - Alternative Test Xpath on Child Element
body: <p>Im trying to use the XSD 1.1 framework to test that the child element of the current scope element contains an attribute. If true I want one schema validation for the element, if false i want another.</p>
  
  <p><strong>Example XML</strong></p>
  
  <pre><code>&lt;!-- XML 1 --&gt;
  &lt;GrandParent name="Sam"&gt;
      &lt;Parent name="Kevin"&gt;
          &lt;Child name="Kyle" id="10" dob="1989-05-02"/&gt;
      &lt;/Parent&gt;
  &lt;/GrandParent&gt;
  
  
  &lt;!-- XML 2 --&gt;
  &lt;GrandParent name="Sam"&gt;
      &lt;Parent name="Kevin" id="10" dob="1975-10-11"/&gt;
  &lt;/GrandParent&gt;
  </code></pre>
  
  <p><strong>XSD 1.1 used for above xml examples</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" &gt;
  
    &lt;xs:element name="GrandParent"&gt;
        &lt;xs:complexType&gt;
            &lt;xs:sequence&gt;
              &lt;xs:element ref="Parent" /&gt;
            &lt;/xs:sequence&gt;
            &lt;xs:attribute name="name" type="xs:string" use="required" /&gt;
        &lt;/xs:complexType&gt;
    &lt;/xs:element&gt;
  
    &lt;xs:element name="Parent"&gt;
        &lt;xs:alternative test="./Child/@id" type="ParentType1" /&gt;
        &lt;xs:alternative                    type="ParentType2" /&gt;
    &lt;/xs:element&gt;
  
    &lt;xs:element name="Child"&gt;
        &lt;xs:complexType&gt;
            &lt;xs:attribute name="name" type="xs:string" use="required" /&gt;
            &lt;xs:attribute name="id" type="xs:integer" use="required" /&gt;
            &lt;xs:attribute name="dob" type="xs:date" use="required" /&gt;
        &lt;/xs:complexType&gt;
    &lt;/xs:element&gt;
  
    &lt;xs:complexType name="ParentType1"&gt;
        &lt;xs:sequence&gt;
            &lt;xs:element ref="Child" /&gt;
        &lt;/xs:sequence&gt;
        &lt;xs:attribute name="name" type="xs:string" use="required" /&gt;
    &lt;/xs:complexType&gt;
  
    &lt;xs:complexType name="ParentType2"&gt;
        &lt;xs:attribute name="name" type="xs:string" use="required" /&gt;
        &lt;xs:attribute name="id" type="xs:integer" use="required" /&gt;
        &lt;xs:attribute name="dob" type="xs:date" use="required" /&gt;
    &lt;/xs:complexType&gt;
  
  &lt;/xs:schema&gt;
  </code></pre>
  
  <p>Im using Xerces xsd 1.1 validation functionality
  <strong>XSD Validation Error</strong></p>
  
  <pre><code>XML 1
  [Error] 1:46: cvc-complex-type.4: Attribute 'id' must appear on element 'Parent'.
  [Error] 1:46: cvc-complex-type.4: Attribute 'dob' must appear on element 'Parent'.
  [Error] 1:100: cvc-complex-type.2.1: Element 'Parent' must have no character or element information item [children], because the type's content type is empty.
  
  XML 2
  Validates
  </code></pre>
  
  <p>The Xpath doesn't seem wrong to me, i've tried a few variations including <code>//Child/@id</code>  and  <code>boolean(Child/@id)</code> but no joy. I dont care what the value of the attribute is, only that it exists in the child element.</p>
  
  <hr>
  
  <p><strong>Update</strong></p>
  
  <p>Thanks to the answer below provided by Michael Kay, I rewrote my schema use asserts instead of alternatives. Here is the updated schema:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;
  
      &lt;xs:element name="GrandParent"&gt;
          &lt;xs:complexType&gt;
              &lt;xs:choice&gt;
                  &lt;xs:element ref="Parent" /&gt;
              &lt;/xs:choice&gt;
              &lt;xs:attribute name="name" type="xs:string" use="required" /&gt;
          &lt;/xs:complexType&gt;
      &lt;/xs:element&gt;
  
      &lt;xs:element name="Child"&gt;
          &lt;xs:complexType&gt;
              &lt;xs:attribute name="name" type="xs:string"  use="required" /&gt;
              &lt;xs:attribute name="id"   type="xs:integer" use="required" /&gt;
              &lt;xs:attribute name="dob"  type="xs:date"    use="required" /&gt;
          &lt;/xs:complexType&gt;
      &lt;/xs:element&gt;
  
      &lt;xs:element name="Parent"&gt;
          &lt;xs:complexType&gt;
              &lt;xs:sequence&gt;
                  &lt;xs:element ref="Child" minOccurs="0"/&gt;
              &lt;/xs:sequence&gt;
              &lt;xs:attribute name="name" type="xs:string"  use="required" /&gt;
              &lt;xs:attribute name="id"   type="xs:integer" use="optional" /&gt;
              &lt;xs:attribute name="dob"  type="xs:date"    use="optional" /&gt;
              &lt;xs:assert test="if (Child/@id) then not(@id or @dob) else (@id and @dob and not(Child))"/&gt;
          &lt;/xs:complexType&gt;
      &lt;/xs:element&gt;
  
  &lt;/xs:schema&gt;
  </code></pre>
  
  <p>The schema seems to work much better, I tested it with the following XML all of which passed or failed as expected</p>
  
  <pre><code>PASS &lt;GrandParent name="Sam"&gt;&lt;Parent name="Kevin"&gt;&lt;Child name="Kyle" id="10" dob="1989-05-02"/&gt;&lt;/Parent&gt;&lt;/GrandParent&gt;
  PASS &lt;GrandParent name="Sam"&gt;&lt;Parent name="Kevin" id="10" dob="1975-10-11"/&gt;&lt;/GrandParent&gt;
  FAIL &lt;GrandParent name="Sam"&gt;&lt;Parent name="Kevin" id="10"/&gt;&lt;/GrandParent&gt;
  FAIL &lt;GrandParent name="Sam"&gt;&lt;Parent name="Kevin" dob="1975-10-11"/&gt;&lt;/GrandParent&gt;
  FAIL &lt;GrandParent name="Sam"&gt;&lt;Parent name="Kevin"/&gt;&lt;/GrandParent&gt;
  </code></pre>