views:

164

answers:

2

I'm trying to put a key in sequence and am being bombarded with errors. It seems I can't do this. Additionally, I am being told my key needs a field and selector, which I have been able to find very little documentation on. (In fact, in desperation, I downloaded Liquid XML Studio [vs. Notepad] and searched it's help files. . . to find NO even reference to the word "selector") Regardless - what is another method I can use to guarantee a unique, not null value for an element, within a sequence? (The content in question is a string)

Please note that without the key element, the schema validates.

The error

Invalid per cvc-complex-type.1.2.4: element {http://www.w3.org/2001/XMLSchema}:key not allowed here (1) in element {http://www.w3.org/2001/XMLSchema}:sequence, expecting [{http://www.w3.org/2001/XMLSchema}:annotation, $, {http://www.w3.org/2001/XMLSchema}:element, {http://www.w3.org/2001/XMLSchema}:group, {http://www.w3.org/2001/XMLSchema}:choice, {http://www.w3.org/2001/XMLSchema}:sequence, {http://www.w3.org/2001/XMLSchema}:any]:

The schema

<?xml version="1.0"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
 targetNamespace="READOO" elementFormDefault="qualified">

  <xs:element name="ReferralCollection">
    <xs:complexType>
      <xs:sequence>
    <xs:key name="URL" type="string" />
        <xs:element maxOccurs="unbounded" name="keyword">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute name="occurrences" type="xs:int" use="required" />
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>
A: 

Please, see if this links can help you:

EDIT: I built schema below several years ago; please, see it fits in your problem:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="urn:asp4d"
    xmlns:asp4d="urn:asp4d">
  <xs:element name="ASP4Developers">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Links" minOccurs="1" maxOccurs="1">
          <xs:keyref name="kUserId" refer="asp4d:UserId">
            <xs:selector xpath="Link"/>
            <xs:field xpath="@UserId"/>
          </xs:keyref>
        </xs:element>
      </xs:sequence>
    </xs:complexType>

    <xs:key name="UserId">
      <xs:selector xpath="Users/User"/>
      <xs:field xpath="@UserId"/>
    </xs:key>

  </xs:element>

</xs:schema>
Rubens Farias
while this does provide more documentation, it does not address my principle problem of needing a key in sequence (unless I am missing something)
Nona Urbiz
interesting, seeing this I tried putting the key after the complexType as you showed, and it worked! But is there no way for it to come first? That seems bizarre.
Nona Urbiz
a key can be used in several places inside your xsd, so makes sense having a broader scope
Rubens Farias
+1  A: 

The key element is not supposed to go inside the sequence element. Instead, you put it as a child of the xs:element that defines ReferralCollection. The selector and field are child elements of the key element that define what is supposed to be unique. Both are XPath expressions. The selector value sets up the XPath context, and the field elements (there can be more than one) define the combination of values that are supposed to be unique. So in your case, the key element might look something like this:

<xs:key name="URL">
  <xs:selector xpath="."/>
  <xs:field xpath="rd:keyword"/>
</xs:key>

The selector here selects the element itself, that is, ReferralCollection. Then, in that context, the field element denotes the values of the keyword elements, which are thus constrained to be unique. The value of an element in XPath is its text content.

I haven't done much with key elements (or XML Schema in general), so some details above might not be correct, but the basic idea is what I explained, so it should be easy to fix any mistakes I made. Oh, also note that I used the rd prefix for your READOO namespace; in my experience using explicit prefixes is always best when dealing with XPath, so you need the appropriate xmlns:rd attribute in your schema to make this work.

EDIT: So it seems you want something like this:

<xs:element name="ReferralCollection">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="URL" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="stem" type="xsd:string"/>
            <xs:element name="keyword" maxOccurs="unbounded">
            ...
            </xs:element>
          ...
  </xs:complexType>

  <xs:key name="URL">
    <xs:selector xpath="./URL"/>
    <xs:field xpath="stem"/>
  </xs:key>
</xs:element>

Is this closer to what you meant? It has URL elements, one or more, each containing a stem element followed by one or more keyword elements. The key constraint should make the contents of the stem elements unique.

jk
thanks for your help!, however, perhaps ironically, when I include the key within ReferralCollection, I am then given an error that complexType is invalid. If I put it within the complexType but outside of the sequence, I am again told that the key is invalid.
Nona Urbiz
Do you put the `key` element after the `complexType` element inside `ReferralCollection`? Because those two elements are acceptable only in that order.
jk
I didn't until I looked @Rubens answer. So does this mean it's simply impossible to force the key to be in sequence? I'd really like to mandate that it come first. Also, would you mind explaining why you used the prefix (which I ended up having to delete actually for my validator) instead of the @ sign (whatsit mean?) that I see elsewhere? [my validator validates it with and without the @ sign interestingly]
Nona Urbiz
What do you mean by "key to be in sequence"? In essence, `key` provides some additional constraints on top of what you can define with the other parts of XML Schema, so it is not really a part of the content description but beside it, so it would not be appropriate to have it inside a content model description.
jk
The `@` sign signifies an attribute. Since in your schema the unique part is not an attribute value but text content, you shouldn't have it. And if your documents are valid, they will validate even when the `key` constraints are improperly written. Try to validate a document that follows the grammar but violates the `key` constraint that you want, and see whether it works then.
jk
woah. . . I think maybe I just understood what's been confusing me, please tell me if I'm on the right track now. I thought a key was a special type of element (one that needs to be unique and not null). But it's actually just altering the element it's placed in to have those characteristics?
Nona Urbiz
wait but then it doesn't make sense why it has a "name"?
Nona Urbiz
by "a key in sequence" I mean I want it to have to be the first element in the complex element (the URL must always come before keywords)
Nona Urbiz
Yes, the `key` element just places uniqueness constraints on the values in the document. Its name lets you refer to it from `keyref` elements. But if I understand you now correctly, you actually want an element named "key" that contains a URL. Is that right?
jk
not quite, sorry I suppose I'm not explaining myself well. (And thanks again for your help). I want an element URL (of which 1+ can be within the root element ReferralCollection) to contain IN ORDER, 1 element of type string called "stem" that is unique throughout the document, followed by an unlimited number of "keyword" elements, each with a mandatory "occurrences" attribute. Looking back, the code I posted does not actually reflect this exactly, but I thought illustrated my more specific need.
Nona Urbiz
this is perfect, thank you so much. before I accept your answer, I'd just like to ask one final thing: as the ReferralCollection is the root, and it contains only one direct child (URL), it seems unnecessary to include the sequence tag, but removing it gives me errors. I know I can use "all" or "any" in its place, and "all" makes sliiightly more sense, but is there a way by which I can remove it entirely? Thank you so much!
Nona Urbiz
actually, im told by my validator that "all" won't work after all as it limits occurrences of "particles" to 0 or 1
Nona Urbiz
No, you can't remove it. When you want an element to have element content, there needs to be a model group in between, that is, one of `all`, `sequence`, or `choice`. When there is only one element, any of these will have the same semantics. I just retained the `sequence` from your original, but would probably use it in this case anyway.
jk