Commons Digester
  1. Commons Digester
  2. DIGESTER-20

CallMethod rule on nested indentical elements cause parameter confusion

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Nightly Builds
    • Fix Version/s: None
    • Labels:
      None
    • Environment:

      Operating System: other
      Platform: Other

      Description

      There's a problem with the CallMethodRule rule using an attribute as parameter
      and matching nested identical elements : the parameter for the last rule matched
      (and the first method call actually done) is used for all previous calls.

      For example, with this XML file :

      <?xml version="1.0"?>
      <toplevel>
      <foo bar="A">
      <foo bar="B">
      <foo bar="A">
      <foo bar="D">
      <foo bar="C">
      <foo bar="B">
      <foo bar="A"/>
      </foo>
      </foo>
      </foo>
      </foo>
      </foo>
      </foo>
      </toplevel>

      If the "bar" attribute of all "foo" elements is appended to a StringBuffer :

      StringBuffer sequence = new StringBuffer();
      digester.push(sequence);
      digester.addCallMethod("*/foo", "append", 1);
      digester.addCallParam("*/foo", 0, "bar");

      the result of sequence.toString() is "AAAAAAA" instead of "ABCDCBA".

      It works fine with body content used as parameter instead of attributes

      <?xml version="1.0"?>
      <toplevel>
      <foo>A
      <foo>B
      <foo>A
      <foo>D
      <foo>C
      <foo>B
      <foo>A
      </foo>
      </foo>
      </foo>
      </foo>
      </foo>
      </foo>
      </foo>
      </toplevel>

      digester.addCallMethod("*/foo", "append", 0);

      It's also fine with different elements :

      <?xml version="1.0"?>
      <toplevel>
      <foo1 bar="A">
      <foo2 bar="B">
      <foo3 bar="A">
      <foo4 bar="D">
      <foo5 bar="C">
      <foo6 bar="B">
      <foo7 bar="A"/>
      </foo6>
      </foo5>
      </foo4>
      </foo3>
      </foo2>
      </foo1>
      </toplevel>

      1. ASF.LICENSE.NOT.GRANTED--CallParamRule.patch
        1.0 kB
        Emmanuel Bourg
      2. ASF.LICENSE.NOT.GRANTED--RuleTestCase.patch
        1 kB
        Emmanuel Bourg
      3. ASF.LICENSE.NOT.GRANTED--Test8.xml
        0.1 kB
        Emmanuel Bourg

        Activity

        Hide
        Emmanuel Bourg added a comment -

        Created an attachment (id=2970)
        Test case (patch for RuleTestCase.java)

        Show
        Emmanuel Bourg added a comment - Created an attachment (id=2970) Test case (patch for RuleTestCase.java)
        Hide
        Emmanuel Bourg added a comment -

        Created an attachment (id=2971)
        Test case (data file)

        Show
        Emmanuel Bourg added a comment - Created an attachment (id=2971) Test case (data file)
        Hide
        Emmanuel Bourg added a comment -

        I just identified the cause of this issue. The attribute value is added to the
        parameter array at the end of the tag, this lets plenty of time for it to be
        overwritten by another attribute matching the same rule. For example :

        1 <toplevel>
        2 <element name="A">
        3 <element name="B">
        4 </element>
        5 </element>
        6 </toplevel>

        with the rules :

        digester.addCallMethod("*/element", "append", 1);
        digester.addCallParam("*/element", 0, "name");

        line 2 : the first parameter array is pushed on the top of the stack, the
        attribute value (A) is set to the bodyText of the CallParamRule but not yet
        written in the parameter array.

        line 3 : the second parameter array is pushed on the stack, the attribute value
        (B) is set to the same CallParamRule bodyText, overwritting the previous value (A).

        line 4 : the end of the 2nd element is reached, the CallParamRule bodyText value
        (B) is added to the 2nd parameter array. The method is then invoked.

        line 5 : the end of the 1st element is reached, the CallParamRule bodyText value
        (B) is added to the 1st parameter array (A was expected). The method is then
        invoked.

        The solution is simply to add the attribute value at the beginning and not at
        the end. For body parameters the value is still added to the array at the end of
        the element of course. I'll post a patch soon.

        Show
        Emmanuel Bourg added a comment - I just identified the cause of this issue. The attribute value is added to the parameter array at the end of the tag, this lets plenty of time for it to be overwritten by another attribute matching the same rule. For example : 1 <toplevel> 2 <element name="A"> 3 <element name="B"> 4 </element> 5 </element> 6 </toplevel> with the rules : digester.addCallMethod("*/element", "append", 1); digester.addCallParam("*/element", 0, "name"); line 2 : the first parameter array is pushed on the top of the stack, the attribute value (A) is set to the bodyText of the CallParamRule but not yet written in the parameter array. line 3 : the second parameter array is pushed on the stack, the attribute value (B) is set to the same CallParamRule bodyText, overwritting the previous value (A). line 4 : the end of the 2nd element is reached, the CallParamRule bodyText value (B) is added to the 2nd parameter array. The method is then invoked. line 5 : the end of the 1st element is reached, the CallParamRule bodyText value (B) is added to the 1st parameter array (A was expected). The method is then invoked. The solution is simply to add the attribute value at the beginning and not at the end. For body parameters the value is still added to the array at the end of the element of course. I'll post a patch soon.
        Hide
        Emmanuel Bourg added a comment -

        Created an attachment (id=3030)
        Patch - Put the attribute value in the parameter array when then beginning of the element is encountered

        Show
        Emmanuel Bourg added a comment - Created an attachment (id=3030) Patch - Put the attribute value in the parameter array when then beginning of the element is encountered
        Hide
        rdonkin@apache.org added a comment -

        patch committed. many thanks.

        • roebrt
        Show
        rdonkin@apache.org added a comment - patch committed. many thanks. roebrt

          People

          • Assignee:
            Unassigned
            Reporter:
            Emmanuel Bourg
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development