Home > OS >  XML check if string contains substring
XML check if string contains substring

Time:06-27

Using a xsd schema I need to check if a value-string of an element contains a specific substring dependent on an child-element <random>. When parsing the string in the end instead of having the string "{rand}" a random number in the range that is defined in the element <random> is supposed to be displayed. That demands that the string "{rand}" is actually included. So for example the upfollowing two code examples should always contain the substring "{rand}" because it has a random-Element included:

<text>Your dice rolled a value of <annotation value='counter'>{rand}<random start='1' end='6'/></annotation>.</text>
<text>Your rolled {rand} times with a dice that had <annotation value='rolls'>6<random start='1' end='4'/></annotation> eyes.</text>

In order to ensure this I was using the following XSD-code containing an assertion:

<xs:element name="text">
    <xs:complexType mixed="true">
        <xs:sequence>
           <xs:choice minOccurs="0" maxOccurs="unbounded">
              <xs:element name="annotation" type="defined_annotation" minOccurs="0" maxOccurs="3"/>
           </xs:choice>
        </xs:sequence>
        <xs:assert test="string-length() ge 3"/>
        <xs:assert test="if (annotation/random) then (contains($value, '{rand}')) else not(annotation/random)"/>
   </xs:complexType>
</xs:element>
<xs:complexType name="defined_annotation" mixed="true">
   <xs:sequence>
       <xs:element name="random" type="random" minOccurs="0" maxOccurs="1"/>
   </xs:sequence>
   <xs:attribute name="value" type="xs:string"/>
</xs:complexType>

Sadly the test if the substring "{rand}" is contained always failed no matter where or how often I have the element included. It even fails if "{rand}" is the only text included in the element <text> at all. Thus I already used several different variations of assertion including the following examples:

<xs:assert test="if (annotation/random) then (contains($value, '{rand}')) else not(annotation/random)"/>
<xs:assert test="if (random) then (contains(text/$value, '{rand}')) else not(random)"/>
<xs:assert test="if (random) then $value/contains('{rand}') else not(random)"/>

All of these compile. None of these work. What am I doing wrong?

CodePudding user response:

I think the main problem with all your attempts is that $value is only defined for simple types in assertions, otherwise the variable is the empty sequence (https://www.w3.org/TR/xmlschema11-1/#assertion-validation: "E's ·governing type definition· does not have {content type} . {variety} = simple) the value is the empty sequence").

What you might be able to do is simply e.g.

<xs:assert test="if (annotation/random) then (contains(., '{rand}')) else not(annotation/random)"/>

. is the context item, i.e. in your case the text element node.

  • Related