Velocity
  1. Velocity
  2. VELOCITY-749

ReferenceInsertionEventHandler called "to often"/need more configuration settings

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Won't Fix
    • Affects Version/s: 1.6.2
    • Fix Version/s: 1.6.x, 1.7
    • Component/s: None
    • Labels:
      None

      Description

      I use the EscapeXmlReference (ReferenceInsertionEventHandler implementation) in our projects to produce valid XHTML.
      But I works not as expected in some situations:

      Given the reference $test as 'Me & Co. Ltd' (for example from context) will output as

      Me & Co. Ltd

      correctly after the EscapeXmlReference.

      But if we enrich the $test reference with some other string before output (#set($test = "* $test *")) we got

      • Me & Co. Ltd *

      and not * Me & Co. Ltd * as output!

      This is because the EscapeReference handler was called two times. First on the (internal) set directive (Me & Co. Ltd > Me & Co. Ltd), second on the real output of $test to the stream (* Me & Co. Ltd *> * Me & Co. Ltd *).
      The javadoc of ReferenceInsertionEventHandler says "Reference 'Stream insertion' event handler. Called with object that will be inserted into stream via value.toString()."
      "inserted into stream" means to me into the real output stream of the template merge, not into internal substreams. So I believe it's a bug or a least an unexpected behaviour because it produce unpredictable results on string operations.

      So the ReferenceInsertionEventHandler needs the possibility to know if the current insertation is an internal or an real output insertation to be able to react on situations as descripted above.

        Activity

        Hide
        Claude Brisson added a comment - - edited

        It's too complex to try to configure it, because the frontier between an internal and a real output insertion is very difficult to define.

        If you want to control precisely when escaping occurs and when it doesn't, you better inherit EscapeXmlReference in a class of yours.

        A quite handy way of handling this, that I often use, is giving prefixes to reference names. For instance, you can have a filter that only escapes references whose name begins by 'xml'.

        public class MyXmlEscape extends EscapeXmlReference
        {
        public Object referenceInsert( String reference, Object value ) {
        if (value == null)

        { return null; }

        if (!value instanceof String || !reference.startsWith("xml"))

        { // do not escape return value; }

        else

        { // escape return super.referenceInsert(reference, value); }

        }
        }

        That way, you can write :

        #set( $test = 'Me & Co. Ltd' )
        #set( $xmltest = " * $test * ")
        $xmltest

        and this will exhibit the expected behaviour.

        Show
        Claude Brisson added a comment - - edited It's too complex to try to configure it, because the frontier between an internal and a real output insertion is very difficult to define. If you want to control precisely when escaping occurs and when it doesn't, you better inherit EscapeXmlReference in a class of yours. A quite handy way of handling this, that I often use, is giving prefixes to reference names. For instance, you can have a filter that only escapes references whose name begins by 'xml'. public class MyXmlEscape extends EscapeXmlReference { public Object referenceInsert( String reference, Object value ) { if (value == null) { return null; } if (!value instanceof String || !reference.startsWith("xml")) { // do not escape return value; } else { // escape return super.referenceInsert(reference, value); } } } That way, you can write : #set( $test = 'Me & Co. Ltd' ) #set( $xmltest = " * $test * ") $xmltest and this will exhibit the expected behaviour.
        Hide
        Claude Brisson added a comment -

        Sophisticated filtering behaviours can be proposed on the wiki, but shouldn't be included in the engine, as use cases are too complex and too different one from another

        Show
        Claude Brisson added a comment - Sophisticated filtering behaviours can be proposed on the wiki, but shouldn't be included in the engine, as use cases are too complex and too different one from another
        Hide
        Marco Rothe added a comment -

        Hmm, I can't find anything about escaping references on the wiki! The current behaviour of the EscapeXmlReference handler is nearly useless if there is no way to distinct between internal and real output insertations. Did you know a way to do that with 'sophisticated filtering' ? I would like to see an example or get an hint.

        Show
        Marco Rothe added a comment - Hmm, I can't find anything about escaping references on the wiki! The current behaviour of the EscapeXmlReference handler is nearly useless if there is no way to distinct between internal and real output insertations. Did you know a way to do that with 'sophisticated filtering' ? I would like to see an example or get an hint.
        Hide
        Marco Rothe added a comment -

        Sorry, my browser did'nt show me your example when I leave my comment :-/

        Show
        Marco Rothe added a comment - Sorry, my browser did'nt show me your example when I leave my comment :-/

          People

          • Assignee:
            Unassigned
            Reporter:
            Marco Rothe
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development