Search code examples
xmlxpathxml-parsingxsd-1.0

What XPath expression should I use in xs:field to select element content?


I am aware that in general one uses /the/path/to/a/node/text() to extract a string value. That has not been sufficient to solve my problem.

I am using XML Schema version 1.0 to define some document types. I am trying to create a very simple keywords section for a document type. So I first create a very simple complex type.

<xs:complexType name="KeywordsList">
    <xs:sequence>
        <xs:element name="tag" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

So now I have a type that can contain a list of any number of elements containing xs:token values. My problem begins with the question of how to forbid duplicates.

I have used xs:key and xs:unique pretty often for this very trivial task, but I have only ever done it for attribute values or more deeply nested elements. For example, if the keyword values were stored in an attribute named value instead I know I could do something like this.

...
<xs:element name="keywords" type="KeywordsList">
    <xs:unique name="KeywordsListUnique">
        <xs:selector xpath="child::tag"/>
        <xs:field xpath="@value"/>
    </xs:unique>
</xs:element>
...

What really confuses me is that <xs:selector xpath="child::tag"/> is enough for the XML parser to locate the values, but I am required to include at least one xs:field tag.

At first I thought I should specify <xs:field xpath="text()"/> to reference the text content of the node, but when I do that I get an error message from OxygenXML.

c-general-xpath: The expression 'text()' is not valid with respect to the XPath subset supported by XML Schema.

I get similar messages for child::text(), ./text(), and a few other similar ones. I have gotten rid of the error messages by using a single dot to reference the current node, but I don't know if . is the correct expression to use.

So what should I put in the xs:field tag?


Solution

  • The answer is, indeed, to use <xs:field xpath="."/> as in this post.