Home > Software engineering >  How to define an element with empty $value dependent on its use?
How to define an element with empty $value dependent on its use?

Time:09-21

Working in XSD 1.1 I have a schema that includes text elements in which I am supposed to mark certain words with the tag "keyword". Something like this:

ex 1: <text>I have a <keyword>specific</keyword> taste.</text>

These keywords can either stand as seen or also be part of a category which is defined as an optional attribute within the keyword element. The keyword either is supposed to refer to such a category, or to have the searched keyword inside as string or to display a combination of both. So they should be freely intermixable like this:

ex 2: <text>The <keyword group='weapon'>sword</keyword> that I used is <keyword group='smithing'/>made of <keyword>steel</keyword>.</text>

So far so good. But now I am supposed to build a condition-structure that also uses these keywords but without showing them inside the text itself. So it is asked for only refering to them like in the second example when only the category is referenced but no string is inside the keyword-element. This is mandatory because all strings inside elements are later supposed to be read by another program. The aim is something like this:

ex 3: <text><condition><keyword group='sword'/><keyword group='handle'/></condition>By now swinging it, the sheer fore is cutting through my <keyword>enemies</keyword>.</text>

In comparison, something like this is supposed to be forbidden as the strings inside the conditioned-keyword-element would be displayed in the string that is supposed to be readable later:

ex 4: <text><condition><keyword group='weapon'>sword</keyword><keyword group='handle'/></condition>By now swinging it, the sheer fore is cutting through my <keyword>enemies</keyword>.</text>

My task now is to forbid such a structure. How do I realise this? In my schema I assume I need to build an assert as part of the condition-element but I am lost on how to do it. I already tried several approaches like this:

ex 5:

<xs:complexType name="condition" mixed="true">
    <xs:sequence>
        <xs:element name="keyword" type="keyword" minOccurs="1" maxOccurs="5"/>        
    </xs:sequence>
    <xs:assert test="string-length($value) = 0"/>
</xs:complexType>

ex 6:

<xs:complexType name="condition" mixed="true">
    <xs:sequence>
        <xs:element name="keyword" type="keyword" minOccurs="1" maxOccurs="5"/>        
    </xs:sequence>
    <xs:assert test="$value eq ''"/>
</xs:complexType>

ex 7:

<xs:complexType name="condition" mixed="true">
    <xs:sequence>
        <xs:element name="keyword" type="keyword" minOccurs="1" maxOccurs="5"/>        
    </xs:sequence>
    <xs:assert test="::child::string-length() = 0"/>
</xs:complexType>

They all are either not catching the case when I have a wrong XML-Code like in example 4 or are even throwing an error-message that the assertion evaluation failed. What am I doing wrong? How do I solve this issue?

CodePudding user response:

I think this can also be done without assertions (or XSD 1.1): the local element declaration for keyword within the complex type of condition can have a different type from the global definition for keyword, and the local definition can have an empty content model.

CodePudding user response:

That is easy if you know XPath 2:

<xs:complexType name="condition" mixed="true">
    <xs:sequence>
        <xs:element name="keyword" type="keyword" minOccurs="1" maxOccurs="5"/>        
    </xs:sequence>
    <xs:assert test="every $keyword in keyword satisfies string-length($keyword) eq 0"/>
</xs:complexType>
  • Related