RE: Keys and Scope

> 
> I'm new to XML and keep getting the feeling that everything 
> is upside-down from my normal understanding of scope.

I have to confess that I suffer from serious brain-ache whenever a key and a
keyref have different scope, and when elements are nested recursively it
gets even worse. 

In this case, I think it's possible to define a rule that the "ref" must
refer to an "id" at EVERY level, but I can't see a way to define the rule
that it must refer to an "id" at SOME level. 

I think there's a fundamental reason for this. To determine whether a
Section is valid according to your rules, you need to look outside that
Section. That means that the rule applies to something larger than a
Section; but Section is the outermost element in your model, so there is
nothing larger than a Section. Or to put it another way, the rules for the
outermost section are different from the rules for inner sections, and
therefore they have different types.

Even with assertions in XSD 1.1, I think you would need to have different
types for the outermost Section and for inner Sections; the outermost
Section could have an assertion:

every $ref in .//Refer satisfies exists($ref/ancestor::Section/Define[@id eq
$ref/@Refer])

You couldn't define this assertion on inner Section elements because one of
the rules of assertions is that only the subtree under the current node is
visible; the ancestor axis wouldn't see anything outside this Section, so
the condition would not be true.

Michael Kay
http://www.saxonica.com/

> 
> I have a Schema defined:
> 
> <?xml version="1.0" encoding="utf-8"?>
> <xs:schema id="XMLSchema2"
>                 targetNamespace="http://tempuri.org/XMLSchema2.xsd"
>                 elementFormDefault="qualified"
>                 xmlns:s="http://tempuri.org/XMLSchema2.xsd"
>                 xmlns:xs="http://www.w3.org/2001/XMLSchema">
>         <xs:element name="Section" type="s:SectionType">
>                 <xs:key name="DefinitionKey">
>                         <xs:selector xpath="s:Define"/>
>                         <xs:field xpath="@name"/>
>                 </xs:key>
>                 <xs:keyref name="DefinitionRef" 
> refer="s:DefinitionKey">
>                         <xs:selector xpath="s:Refer"/>
>                         <xs:field xpath="@ref"/>
>                 </xs:keyref>
>         </xs:element>
>         <xs:complexType name="SectionType" mixed="true">
>                 <xs:sequence minOccurs="1" maxOccurs="1">
>                         <xs:sequence minOccurs="0" 
> maxOccurs="unbounded">
>                                 <xs:element name="Define" 
> type="s:DefineType"/>
>                         </xs:sequence>
>                         <xs:choice minOccurs="0" 
> maxOccurs="unbounded">
>                                 <xs:element name="Refer" 
> type="s:ReferType"/>
>                                 <xs:element ref="s:Section"/>
>                         </xs:choice>
>                 </xs:sequence>
>         </xs:complexType>
>         <xs:complexType name="DefineType">
>                 <xs:complexContent>
>                         <xs:extension base="s:SectionType">
>                                 <xs:attribute name="name" 
> type="xs:string"/>
>                         </xs:extension>
>                 </xs:complexContent>
>         </xs:complexType>
>         <xs:complexType name="ReferType">
>                 <xs:complexContent>
>                         <xs:extension base="s:SectionType">
>                                 <xs:attribute name="ref" 
> type="xs:string"/>
>                         </xs:extension>
>                 </xs:complexContent>
>         </xs:complexType>
> </xs:schema>
> 
> I have the following instance document:
> 
> <?xml version="1.0" encoding="utf-8" ?>
> <Section xmlns="http://tempuri.org/XMLSchema2.xsd">
>         <Define name="one"/>
>         <Refer ref="one"/> <!-- Allow: defined in current node. -->
>         <Refer ref="two"/> <!-- Error: not defined in current 
> or ancestor node. -->
>         <Section>
>                 <Define name="two"/>
>                 <Refer ref="one"/> <!-- Allow: defined in 
> ancestor node. -->
>                 <Refer ref="two"/> <!-- Allow: defined in 
> current node. -->
>         </Section>
> </Section>
> 
> I would like to define the keys and keyrefs in the schema 
> such that I can enforce the rules in the comments above, but 
> I'm not finding a way to do this.
> 
> Basically, I'm thinking of a node and all it's child nodes as 
> my scope, and would like to Refer to anything Defined in the 
> same scope, but disallow any References to things Defined out 
> of scope.
> 
> The closest I've been able to come is the reverse, where I 
> can Refer to anything Defined in the current or any 
> descendant node, by changing:
> 
>                 <xs:key name="DefinitionKey">
>                         <xs:selector xpath=".//s:Define"/>
>                         <xs:field xpath="@name"/>
>                 </xs:key>
> 
> Am I hopelessly stuck in a mindset that just doesn't work 
> with XML?  Or is there an obvious solution I'm just overlooking?
> 
> Any help would be greatly appreciated.
> 
> Thanks,
> Matt Knowles
> 
> 
> 

Received on Wednesday, 12 November 2008 21:24:19 UTC