3

When I run the following xquery in MarkLogic":

xquery version "1.0-ml";

let $envelope := <envelope xmlns="http://marklogic.com/entity-services"> 
                                <info>hello</info>
                             </envelope>

return fn:data($envelope/es:info)

I receive this error:

[1.0-ml] XDMP-NONMIXEDCOMPLEXCONT: fn:data(hello) -- Node has complex type with non-mixed complex content

Strangely, when I rename the info-node to info1 for instance the code works as expected:

xquery version "1.0-ml";

let $envelope := <envelope xmlns="http://marklogic.com/entity-services">
                         <info1>hello</info1>
                     </envelope>

return fn:data($envelope/es:info1)

result is: hello (as expected)

Can someone explain this black magic to me?

3 Answers3

1

I guess this is because the schema entity-type.xsd defines the elements as non-mixed:

<xs:complexType name="InfoType">
    <xs:sequence>
      <xs:element ref="es:title"/>
      <xs:element ref="es:version"/>
      <xs:element ref="es:base-uri" minOccurs="0"/>
      <xs:element ref="es:description" minOccurs="0"/>
    </xs:sequence>
</xs:complexType>

<xs:element name="info" type="es:InfoType"/>

A element can be of mixed content if it has a mixed="true" attribute. Because you cannot change the schema in this case, i'd try using string().

declare namespace es = "http://marklogic.com/entity-services";

let $envelope := <envelope xmlns="http://marklogic.com/entity-services"> 
                    <info>
                      <title>hello</title>
                      <version>1.0</version>
                    </info>
                 </envelope>

return $envelope/es:info/string()

This gives you hello1.0 as a result if this is what you wanted.

Your example with info1 works, because this element is not defined in the schema (and thus wouldn't be a valid xml).

Wagner Michael
  • 2,172
  • 1
  • 15
  • 29
1

Because fn:data() has potential interactions with schemas, consider using fn:string() to get the text of an element as a string.

ehennum
  • 7,295
  • 13
  • 9
0

MarkLogic tries to retrieve a typed value from your data when using fn:data(). MarkLogic will look for an appropriate schema for that purpose. Since you are using the entity-services namespace, it will look for the entity-services schema. This schema has a particular definition of the info element (as correctly mentioned by Michael), which doesn't match the way you use it.

Using fn:string() instead of fn:data() is usually more robust, since it will by-pass data type checking. Using an element name which is not defined in the entity-services schema is gives you a quick fix that will work now, but it might be tricky to guarantee it will work in future as well.

Personally, I'd advice to use the entity-services namespace as intended. If you need to put in additional elements, put them in a different namespace, with or without an accompanying schema. Or, simply drop the namespace entirely.

HTH!

grtjn
  • 20,254
  • 1
  • 24
  • 35
  • Thanks for this explanation! It wasn't clear from the marklogic documentation, that fn:data() actually searched for schema's. And actually we were using xdmp:hash64() which uses fn:data underwater, so in our case the solution was to use fn:string(xdmp:hash64($variable)) – T. Philippi Jan 08 '19 at 16:17