Search code examples
xmlxpathxpath-2.0altovaxmlspy

Altova XMLSpy - Xpath "Unexpected 'atomic' item xs:string" error from tokenize() function


I'm using Altova XMLSpy and I'm having trouble with the Xpath tokenize() function using Xpath 2.0.

I have an XML containing this tag which contains the value I need:

<REF TyCd="INVREF2">VVQFAR CIG ZA5180AAB6</REF>

This is the Xpath I made to retrieve the value I need:

if (index-of(tokenize(/InvoiceMsg/INVOICE/REFS/REF[@TyCd='INVREF2'], ' '), 'CIG') > 0)
then
    tokenize(/InvoiceMsg/INVOICE/REFS/REF[@TyCd='INVREF2'], ' ')[index-of(tokenize(/InvoiceMsg/INVOICE/REFS/REF[@TyCd='INVREF2'], ' '), 'CIG') + 1]
else
    ''

The error occurs in the third use of the tokenize() function and says:

Unexpected 'atomic' item xs:string Details XPTY0020: The context item in an axis step must be a node

Moreover, if i use a fixed string, like this

tokenize(/InvoiceMsg/INVOICE/REFS/REF[@TyCd='INVREF2'], ' ')[index-of(tokenize('VVQFAR CIG ZA5180AAB6', ' '), 'CIG') + 1]

the error does not occur.

The question is: why error occurs only there (and not in the if statement, for example) and what can I do?


Solution

  • tokenize() returns a sequence of strings, so in a predicate applied to the result of tokenize(), the context item is a string. You can't use a path expression when the context item is a string. You need to bind a variable externally, and use this in the predicate: [index-of(tokenize($root/InvoiceMsg/....)]

    Even better, bind a variable to the result of tokenize(/InvoiceMsg/INVOICE/REFS/REF[@TyCd='INVREF2'] since you use the expression more than once.

    However, this is problematic in XPath 2.0 which has no "let" expression. If you have XPath 3.0/3.1 you can bind a variable using "let". If not, you only have "for", which only allows you to bind a singleton:

    for $root in /
    return ..... [index-of(tokenize($root/InvoiceMsg/....)]