Search code examples
springxpathspring-el

Spring Spel XPATH Expression for Namespace but no prefix


Issue: Trying to build the correct XPATH using SpEL xpath to correlate on a the "Name" tag value where the root tag has a namespace but no prefix.

Error: Unexpected token. Expected 'rparen())' but was 'identifier' It's complaining about & #39; where I am trying to make a single quote for the xpath evaluation.

XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://www.foo.com">
<id></id>
<Name>test</Name>
</root>

Spring Config

<aggregator 
    id="agg1" 
    input-channel="requestChannel"
    output-channel="outputChannel" 
    discard-channel="garbageCanChannel"
    ref="blah" 
    method="combine"
    expire-groups-upon-completion="true"
    correlation-strategy-expression="#xpath(payload, '//*[local-name()]=&#39;Name&#39;/text()')"
    release-strategy="blah"
    release-strategy-method="timeToRelease"
    send-partial-result-on-expiry="false"
    send-timeout="60000"
    group-timeout="60000"
    />

Update:

So after downloading spring source and tracing the issue. It's seem that during the tokenization execution in the method below, Spring is treating the "Name" as a identifier instead of as part of the string literal. At least this is the difference between a working instance and a failing instance.Most likely i'm not escaping it correctly.

Class:InternalSpelExpressionParser.java Method:doParseExpression

this.expressionString = "#xpath(payload, '//*[local-name()=Name]')"//This works
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()=Name]'](16,45), [RPAREN())](45,46)]


this.expressionString = "#xpath(payload, '//*[local-name()='Name']')"//Thisfails
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()='](16,35), [IDENTIFIER:Name](35,44), [LITERAL_STRING:']'](44,47), [RPAREN())](47,48)]

Solution: ...

correlation-strategy-expression="#xpath(payload, '//*[local-name()=''Name'']/text()')"

Correct String Literal: -You can see that it is now correct because the tokenization process is putting everything within the string literal token.

[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()=''Name'']/text()'](16,56), [RPAREN())](56,57)]

Additional Debug Notes:

When pulling out the spring git here:

https://github.com/spring-projects/spring-framework

  1. Take all of the projects.
  2. At the root is "import=into-eclipse.bat" or "import-into-idea" that I did not see. You can execute that to fully build and check-out everything you need locally and import the projects so you can trace a issue.

Solution

  • Your expression as posted will produces invalid XPath. It should have closing square bracket just before /text() instead :

    '//*[local-name()=&#39;Name&#39;]/text()'
    

    Or maybe using double single-quotes to escape, as suggested here :

    '//*[local-name()=''Name'']/text()'