Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unknown attribute 'ref' in parser::pop_element() for certain files #436

Closed
MarioLiebisch opened this issue Jan 10, 2020 · 8 comments
Closed

Comments

@MarioLiebisch
Copy link

This might be the same issue as reported in issue #433, but wanted to create a separate one just in case.

From my observations this seems to be triggered when cells were auto-populated by excel after dragging the corner of a cell (or multiple cells), i.e. doing this:
xlnt-cell-drag

I've create two files that seem to be identical, but one was created by writing down the formulas by hand, while the other one was created dragging the first row down:

@tfussell
Copy link
Owner

Thanks for the detailed bug report. I'll try to work through it in the next few days.

@gamearea
Copy link

same problem

@beedaddy
Copy link

beedaddy commented Feb 6, 2020

I'm having this issue, too (but since I only received the file, I don't know about auto-populated cells).

I get the error:

terminate called after throwing an instance of 'xml::parsing'
  what():  xl/worksheets/sheet1.xml:2:2206: error: unexpected attribute 'ref'

Example file:
broken2.xlsx

@sukoi26
Copy link
Contributor

sukoi26 commented Feb 21, 2020

for broken2 the code xml for the cell at 2206 sheet1

<c r="A8" s="12"><f t="shared" ref="A8:A71" si="0">A7+1</f><v>3</v></c>
i suspect the level search element in xlx_consummer.cpp
level 1 is level 2 i does it parse the attributes map ?

@sukoi26
Copy link
Contributor

sukoi26 commented Feb 28, 2020

to specify , never below in 2 level call parse attribute_map?

    int level = 1; // nesting level
        // 1 == <c>
        // 2 == <v>/<is>/<f>
        // exit loop at </c>
    while (level > 0)
    {
        xml::parser::event_type e = parser->next();
        switch (e)
        {
        case xml::parser::start_element: {
            ++level;
            break;
        }
        case xml::parser::end_element: {
            --level;
            break;
        }
        case xml::parser::characters: {
            // only want the characters inside one of the nested tags
            // without this a lot of formatting whitespace can get added
            if (level == 2)
            {
                // <v> -> numeric values
                // <is><t> -> inline string
                if (string_equal(parser->name(), "v"))
                {
                    c.value += std::move(parser->value());
                }
                 // <f> formula
                else if (string_equal(parser->name(), "f"))
                {
                    c.formula_string += std::move(parser->value());
                }
            }
            else if (level == 3)
            {
                // <is><t> -> inline string
                if (string_equal(parser->name(), "t"))
                {
                    c.value += std::move(parser->value());
                }
            }
            break;
        }
        case xml::parser::start_namespace_decl:
        case xml::parser::end_namespace_decl:
        case xml::parser::start_attribute:
        case xml::parser::end_attribute:
        case xml::parser::eof:
        default: {
            throw xlnt::exception("unexcpected XML parsing event");
        }
        }
    }

in second in libstudxml, the next() use pop()

  parser::event_type parser::
  next ()
  {
    if (state_ == state_next)
      return next_ (false);
    else
    {
      // If we previously peeked at start/end_element, then adjust
      // state accordingly.
      //
      switch (event_)
      {
      case end_element:
        {
          if (!element_state_.empty () &&
              element_state_.back ().depth == depth_)
            pop_element ();

          depth_--;
          break;
        }
      case start_element:
        {
          depth_++;
          break;
        }
      default:
        break;
      }

      state_ = state_next;
      return event_;
    }
  }

pop() in comment check attribute unhandled

  void parser::
  pop_element ()
  {
    // **Make sure there are no unhandled attributes left.**
    //
    const element_entry& e (element_state_.back ());
    if (e.attr_unhandled_ != 0)
    {
      // Find the first unhandled attribute and report it.
      //
      for (attribute_map_type::const_iterator i (e.attr_map_.begin ());
           i != e.attr_map_.end (); ++i)
      {
        if (!i->second.handled)
          throw parsing (
            *this, "unexpected attribute '" + i->first.string () + "'");
      }
      assert (false);
    }

    element_state_.pop_back ();
  }

So, it seem that in level2 something missing in parse <f> as

for (auto &attr : parser->attribute_map())
    {
        if (string_equal(attr.first.name(), "ref"))
        {
            c.ref = Cell_Formula_ Reference(row_arg, attr.second.value);
        }
...

@RockinRoel
Copy link

RockinRoel commented Mar 16, 2020

I've encountered a spreadsheet that has the same issue: https://eba.europa.eu/sites/default/documents/files/document_library/881117/EBA%20Validation%20Rules%20March%202020%20deactivation.xlsx

For now, I've worked around it by looping over, but ignoring, all attributes.

diff --git a/source/detail/serialization/xlsx_consumer.cpp b/source/detail/serialization/xlsx_consumer.cpp
index ea64b131..2898cbec 100644
--- a/source/detail/serialization/xlsx_consumer.cpp
+++ b/source/detail/serialization/xlsx_consumer.cpp
@@ -302,6 +302,9 @@ Cell parse_cell(xlnt::row_t row_arg, xml::parser *parser)
             throw xlnt::exception("unexcpected XML parsing event");
         }
         }
+        for (const auto &attr : parser->attribute_map()) {
+            (void)attr;
+        }
     }
     return c;
 }

hos-b pushed a commit to hos-b/wsautofill that referenced this issue Apr 1, 2020
possible TODO: change excel backend lib to troldal/OpenXLSX to overcome the known XLNT bug (tfussell/xlnt#436)
ucomus added a commit to ucomus/xlnt that referenced this issue Sep 28, 2020
@doomlaur
Copy link
Contributor

doomlaur commented Nov 30, 2021

I can confirm that this issue is present in xlnt v1.5.0 (latest stable release). However, compiling xlnt from the latest commit (currently 3a279fc from 2021-08-22) fixed this issue, so it seems that no fix is needed anymore.

@tfussell
Copy link
Owner

As reported above, this was fixed by ignoring extra attributes in 0ecad78. I've also just merged a PR (#647) which adds support for shared formulas which was the original trigger for this error. As a result, I'm going to close this old issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants