title: How to restrict attributes of child elements based on parent attribute or position in XSD schema
body: <p>Trying to design a XSD Schema for this sample XML. From external API so can't change it. Problem I run into is how to restrict the attributes on the rows.</p>
  
  <pre><code>&lt;?xml version='1.0' encoding='UTF-8'?&gt;
  &lt;eveapi version="2"&gt;
    &lt;currentTime&gt;2014-04-21 06:07:26&lt;/currentTime&gt;
    &lt;result&gt;
      &lt;characterID&gt;123&lt;/characterID&gt;
      &lt;name&gt;Me&lt;/name&gt;
      &lt;rowset name="skills" key="typeID" columns="typeID,skillpoints,level,published"&gt;
        &lt;row typeID="3424" skillpoints="16000" level="3" published="1" /&gt;
        &lt;row typeID="3318" skillpoints="2829" level="2" published="1" /&gt;
        &lt;row typeID="3425" skillpoints="2829" level="2" published="1" /&gt;
        &lt;row typeID="3451" skillpoints="500" level="1" published="1" /&gt;
      &lt;/rowset&gt;
      &lt;rowset name="certificates" key="certificateID" columns="certificateID"&gt;
          &lt;row certificateID="1"/&gt;
      &lt;/rowset&gt;
      &lt;rowset name="corporationRoles" key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/rowset&gt;
      &lt;rowset name="corporationRolesAtHQ" key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/rowset&gt;
      &lt;rowset name="corporationRolesAtBase" key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/rowset&gt;
      &lt;rowset name="corporationRolesAtOther" key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/rowset&gt;
      &lt;rowset name="corporationTitles" key="titleID" columns="titleID,titleName"&gt;
        &lt;row titleID="1" titleName="Member" /&gt;
        &lt;row titleID="2" titleName="Member Senior" /&gt;
        &lt;row titleID="8192" titleName="Research Director" /&gt;
      &lt;/rowset&gt;
    &lt;/result&gt;
    &lt;cachedUntil&gt;2014-04-21 12:04:26&lt;/cachedUntil&gt;
  &lt;/eveapi&gt;
  </code></pre>
  
  <p>And I've got this from my IDE generating based on the sample.</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;
    &lt;xs:element name="eveapi" type="eveapiType"/&gt;
    &lt;xs:complexType name="rowType"&gt;
      &lt;xs:simpleContent&gt;
        &lt;xs:extension base="xs:string"&gt;
          &lt;xs:attribute type="xs:string" name="typeID" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="skillpoints" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="level" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="published" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="certificateID" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="roleID" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="roleName" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="titleID" use="optional"/&gt;
          &lt;xs:attribute type="xs:string" name="titleName" use="optional"/&gt;
        &lt;/xs:extension&gt;
      &lt;/xs:simpleContent&gt;
    &lt;/xs:complexType&gt;
    &lt;xs:complexType name="rowsetType"&gt;
      &lt;xs:sequence&gt;
        &lt;xs:element type="rowType" name="row" maxOccurs="unbounded" minOccurs="0"/&gt;
      &lt;/xs:sequence&gt;
      &lt;xs:attribute type="xs:string" name="name" use="optional"/&gt;
      &lt;xs:attribute type="xs:string" name="key" use="optional"/&gt;
      &lt;xs:attribute type="xs:string" name="columns" use="optional"/&gt;
    &lt;/xs:complexType&gt;
    &lt;xs:complexType name="eveapiType"&gt;
      &lt;xs:sequence&gt;
        &lt;xs:element type="xs:string" name="currentTime"/&gt;
        &lt;xs:element type="resultType" name="result"/&gt;
        &lt;xs:element type="xs:string" name="cachedUntil"/&gt;
      &lt;/xs:sequence&gt;
      &lt;xs:attribute type="xs:string" name="version"/&gt;
    &lt;/xs:complexType&gt;
    &lt;xs:complexType name="resultType"&gt;
      &lt;xs:sequence&gt;
        &lt;xs:element type="xs:string" name="characterID"/&gt;
        &lt;xs:element type="xs:string" name="name"/&gt;
        &lt;xs:element type="rowsetType" name="rowset" maxOccurs="unbounded" minOccurs="0"/&gt;
      &lt;/xs:sequence&gt;
    &lt;/xs:complexType&gt;
  &lt;/xs:schema&gt;
  </code></pre>
  
  <p>But it just merges the attributes so <code>&lt;row&gt;</code> allows any or all of the attributes no matter the <code>&lt;rowset&gt;</code>.</p>
  
  <p>Any help would be great as I've tried everything I could think of and most give errors in XSD validators about using abstract wrong or being indeterminate somewhere.</p>
  
  <p>I'm still interested in a XSD only solution but just in case someone else has similar problem and find this I'll relate a two step solution using XSL style sheet/transform and XSD.</p>
  
  <h2># Two Step Solution #</h2>
  
  <pre><code>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
      &lt;xsl:output method="xml"
          version="1.0"
          encoding="utf-8"
          omit-xml-declaration="no"
          standalone="no"
          indent="yes"/&gt;
      &lt;xsl:template match="rowset"&gt;
          &lt;xsl:choose&gt;
              &lt;xsl:when test="@name"&gt;
                  &lt;xsl:element name="{@name}"&gt;
                      &lt;xsl:copy-of select="@key"/&gt;
                      &lt;xsl:copy-of select="@columns"/&gt;
                      &lt;xsl:apply-templates/&gt;
                  &lt;/xsl:element&gt;
              &lt;/xsl:when&gt;
              &lt;xsl:otherwise&gt;
                  &lt;xsl:copy-of select="."/&gt;
                  &lt;xsl:apply-templates/&gt;
              &lt;/xsl:otherwise&gt;
          &lt;/xsl:choose&gt;
      &lt;/xsl:template&gt;
      &lt;xsl:template match="@*|node()"&gt;
          &lt;xsl:copy&gt;
              &lt;xsl:apply-templates select="@*|node()"/&gt;
          &lt;/xsl:copy&gt;
      &lt;/xsl:template&gt;
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>The result ends up looking something like this:</p>
  
  <pre><code>&lt;?xml version='1.0' encoding='UTF-8'?&gt;
  &lt;eveapi version="2"&gt;
    &lt;currentTime&gt;2014-04-21 06:07:26&lt;/currentTime&gt;
    &lt;result&gt;
      &lt;characterID&gt;123&lt;/characterID&gt;
      &lt;name&gt;Me&lt;/name&gt;
      &lt;skills key="typeID" columns="typeID,skillpoints,level,published"&gt;
        &lt;row typeID="3424" skillpoints="16000" level="3" published="1" /&gt;
        &lt;row typeID="3318" skillpoints="2829" level="2" published="1" /&gt;
        &lt;row typeID="3425" skillpoints="2829" level="2" published="1" /&gt;
        &lt;row typeID="3451" skillpoints="500" level="1" published="1" /&gt;
      &lt;/skills&gt;
      &lt;certificates key="certificateID" columns="certificateID"&gt;
          &lt;row certificateID="1"/&gt;
      &lt;/certificates&gt;
      &lt;corporationRoles key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/corporationRoles&gt;
      &lt;corporationRolesAtHQ key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/corporationRolesAtHQ&gt;
      &lt;corporationRolesAtBase key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/corporationRolesAtBase&gt;
      &lt;corporationRolesAtOther key="roleID" columns="roleID,roleName"&gt;
        &lt;row roleID="1" roleName="roleDirector" /&gt;
      &lt;/corporationRolesAtOther&gt;
      &lt;corporationTitles key="titleID" columns="titleID,titleName"&gt;
        &lt;row titleID="1" titleName="Member" /&gt;
        &lt;row titleID="2" titleName="Member Senior" /&gt;
        &lt;row titleID="8192" titleName="Research Director" /&gt;
      &lt;/corporationTitles&gt;
    &lt;/result&gt;
    &lt;cachedUntil&gt;2014-04-21 12:04:26&lt;/cachedUntil&gt;
  &lt;/eveapi&gt;
  </code></pre>
  
  <p>To just give quick explanation what it does is replace any <code>rowset</code> element that have <code>name</code> attribute with element equal to attribute value and copies the remaining attributes over to the new element. It'll work with recursive <code>rowset</code>s which I needed and some may not include names on sub-elements so need to handle that as well by just using a regular element copy in that case. The rest is simple standard tree copy. Now that the XML is transform the XSD is easy to make and in my case my IDE can even make them for me ;-)</p>