Jump to content

Using Xpath In A Schema


Jack McKalling

Recommended Posts

Hmm, I just started out on learning XPath for Schema recently. I am trying to define a model for an xml document, which in turn will describe the syntax of some text file used in a Java application.I just don't understand how XPath works. There are lots of examples in the tutorial, and theoretically I understand, but in practice, it would just not work for me :) I have this xml fragment:

<commandTemplate schema binding><metainfo><components><inlinecomment> <marker char="" /> <closer char="" /> </inlinecomment><argumentList> <separator char="" /> </argumentList><valueList> <separator char="" /> </valueList><commandName> <marker char="" /> </commandName><argumentName> <marker char="" /> </argumentName></components></metainfo></commandTemplate>
And I want the schema to force uniqueness on each and evere "char" attribute here. And this would not work at all:
<!-- ... --><xs:element name="commandTemplate"><xs:complexType> <!-- shortened out --> </xs:complexType><xs:key name="keyChar"><xs:selector xpath="marker | separator | closer"></xs:selector><xs:field xpath="@char"></xs:field></xs:key></xs:element><!-- ... -->

The point is, I am unsure if my XML editor (using Eclipse IDE) show the error in any xml document using this schema, if it has non-unique char attributes. I just assume it does, but I can't find a working example of the key element with due XPath expressions.Edit: I found bits of information about that Eclipse might not support binding between keys and elems/attris, through the modeling system. I think it means my code could be correct, but that only the editor cannot tell if the xml document conforms the xsd in that way. Thus, I cannot know what I am doing :) So, how to lay this binding between "char" attributes and an xs:key?

Link to comment
Share on other sites

That's an interesting element here... I hadn't heared of it (or maybe I did... but I surely never knew how to use it).The easiest way (and the one I've been using in such cases) is to use the datatype xs:id on the char attribute, where the char attribute is declared at the top level, like:

<xs:element name="commandTemplate"><xs:complexType> <!-- shortened out --> </xs:complexType></xs:element><xs:attribute name="char" type="xs:id" />

And then refer to it whenever you normally need to declare it, like:

<xs:element name="marker"><xs:complexType><xs:attribute ref="char" /></xs:complexType></xs:element>

If you also need to place in some restrictions to xs:id (e.g. you want only one character, not several), you can do so as a restriction to the top level attribute itself, like:

<xs:attribute name="char"><xs:simpleType><xs:restriction base="xs:id"><xs:length value="1"/></xs:simpleType></xs:attribute>

Link to comment
Share on other sites

Thanks, I hadn't thought about declaring the attribute at toplevel, I see an ID would then work in this case.However it does restrict you at some point, where the xs:key element could give flexibility. It is never mentioned in the tutorial, that is probably why you didn't see it, it's syntax is only stated in the reference even without an example.I am trying the xs:ID type now. Edit:aaaaaaaaaaaaaaaaaaaa!!! I got it to work! I tried your suggestion, but I got something else working instead :)The xs:key element does work and also validates unique characters, but my XPath was just incorrect, as I suspected. I had declared a local namespace, which I had to use inside the XPath. I would have never guessed it, never thought the XPath works that way.Guess where I found the sollution?In the W3C.org Schema Definition document itself! Just open the namespace in a browser and open the schema file. It exactly shows how xs:keys work. :)If you specify an element name, you should specify the namespace too. And what I also discovered, is that the W3C Schema file does not fully support XPath in the respected xs:selector and xs:field elements. I could not understand why I wasn't allowed to use "descendant::" in my XPath, and this explains why.Thanks for your help :)

Link to comment
Share on other sites

Oh... so it was the XPath namespace thing. Well, maybe if you said your XML is in a namespace (and/or if the sample showed it), I would have guessed that it was the cause :) . Yes, in XPath (in any environment), unless you explicitly specify the namespace with a prefix (that is previously registered in a different fashion, depending on the environment; in this case in the schema document), the element is assumed to be in no namespace.

Link to comment
Share on other sites

I agree, I should have mentioned it. It must have been the fact that I'm new with XPath, and therefor never thought that would be an issue.In fact, I disturbingly thought that the Xpath would take the expression at clientside (the validating xml file) instead of schema-side, conforming the fully qualified names. Thus, it never occured to me I should mention it. I even took the little time to shorten the example!Hmm, it always proves to be something different as to what you expect of a problem, but I don't like to be verbose in my explanation either.

Link to comment
Share on other sites

Man :) I just don't get it.Now it said that I must NOT specify the namespace, or else it wouldn't work. Right now there are two keys, the first needs the namespace specifically specified or it doesn't work, and the other precisely the opposite!!But both elements are just the same.. And Eclipse just wouldn't give even any little tiny bit of error message, even no error number, only a red mark.What am I supposed to do then? :) See the xsd here. In particular, see the difference between the selectors in "kChar" and "kDataType" key elements (and not the fact that one is an xs:unique). In this state, no errors occur. How come ??

Link to comment
Share on other sites

What validator are you using? Using XSV, your schema is valid. I was able to produce the following XML with it (automatically, thanks to my IDE - Stylus Studio), that also validates with all of the validators I tried (Saxonica 8.9.0.3, Java built-in, MSXML 4.0 DOM, MSXML 6.0 DOM, MSXML 4.0 SAX, MSXML 6.0 SAX, .NET XML Parser):

<?xml version="1.0"?><p1:commandTemplate xmlns:p1="http://www.prof-creations.com/CommandParameterLanguage" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.prof-creations.com/CommandParameterLanguage file:///d:/Desktop/CPLSchema.xsd">	<p1:metainfo>		<p1:components>			<!--Element p1:inlineComment, maxOccurs=unbounded-->			<p1:inlineComment>				<p1:marker char="!"/>				<!--Element p1:closer is optional-->				<p1:closer char="@"/>			</p1:inlineComment>			<p1:inlineComment>				<p1:marker char="#"/>				<!--Element p1:closer is optional-->				<p1:closer char="$"/>			</p1:inlineComment>			<p1:inlineComment>				<p1:marker char="%"/>				<!--Element p1:closer is optional-->				<p1:closer char="^"/>			</p1:inlineComment>			<p1:commandName>				<p1:marker char="="/>				<p1:format>[a-zA-Z]+</p1:format>			</p1:commandName>			<p1:argumentName>				<p1:marker char="*"/>				<p1:format>[a-zA-Z]+</p1:format>			</p1:argumentName>			<p1:argumentList>				<p1:separator char=":"/>			</p1:argumentList>			<p1:valueList>				<p1:separator char=";"/>			</p1:valueList>		</p1:components>		<p1:datatypes>			<!--'Choice' block, maxOccurs=unbounded-->			<p1:number idname="string" test="string">				<!--Attribute test is optional-->				<!--Attribute idname is optional-->				<p1:format>[a-zA-Z]+</p1:format>				<!--Element p1:valueLimit is optional-->				<p1:valueLimit>([1-9]|1[0-5])</p1:valueLimit>			</p1:number>			<p1:number idname="string" test="string">				<!--Attribute test is optional-->				<!--Attribute idname is optional-->				<p1:format>[a-zA-Z]+</p1:format>				<!--Element p1:valueLimit is optional-->				<p1:valueLimit>([1-9]|1[0-5])</p1:valueLimit>			</p1:number>			<p1:number idname="string" test="string">				<!--Attribute test is optional-->				<!--Attribute idname is optional-->				<p1:format>[a-zA-Z]+</p1:format>				<!--Element p1:valueLimit is optional-->				<p1:valueLimit>([1-9]|1[0-5])</p1:valueLimit>			</p1:number>		</p1:datatypes>	</p1:metainfo></p1:commandTemplate>

Also, keep in mind that attributes are by default in no namespace. In

<p1:number idname="string" test="string">

both the "idname" and "test" attribute are in no namespace, even though their element is in a namespace. And yet, you have

<xs:field xpath="@cpl:idname" />

which would match the XML above if we had

<p1:number p1:idname="string" test="string">

AFAIK, the same goes for any names in the schema. When you have

<xs:key name="kDataType">

you should refer to it with

refer="kDataType"

not with

refer="cpl:kDataType"

Link to comment
Share on other sites

Hmm, I guess that the XML editor of Eclipse IDE is not particularly well suited, as it is, not giving error messages.Though after I posted the above, I severly tested all possibilities I had in mind, I finaly came to the conclusion that I was trying to make a "key" out of a unique attribute (it was thus optional and gave an error if the so called key was null), as well as using a namespace for the attributes, indeed like you say.The document you show is indeed valid, and I stated no errors would occur with me either with the schema I linked to, however, it is not in the form I want it to be. You can clearly see that all the "idname" attributes may be identical, for which I haven't keyed them for :) You are right about the namespacing, I should declare the attributes with a namespace too if I want to refer to them with it. Everything defined in this schema belongs to this "Command Parameter Language" afterall :)So this is what I did wrong:1) Made an optional field a key (unchecked error by xsd)2) Incorrectly referred to them with a namespace

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...