sissaschool / elementpath

XPath 1.0/2.0/3.0/3.1 parsers and selectors for ElementTree and lxml
MIT License
72 stars 20 forks source link

XPath 2/3 expression min(.//row/count(entry)) doesn't parse with XPath3Parser: elementpath.exceptions.ElementPathTypeError: 'entry' proxy function at line 1, column 18: [err:XPST0017] unknown function 'entry' #78

Open martin-honnen opened 1 month ago

martin-honnen commented 1 month ago

I find that the XPath 2 and 3 expression min(.//row/count(entry)) doesn't parse with the XPath3Parser (it parses with the XPath2 default parser), the error I get is elementpath.exceptions.ElementPathTypeError: 'entry' proxy function at line 1, column 18: [err:XPST0017] unknown function 'entry'.

Example Python code:

from elementpath import select
from elementpath.xpath3 import XPath3Parser

from xml.etree import ElementTree

root = ElementTree.XML('''      <table frame="all" rowsep="1" colsep="1" id="flowers_table">
        <title>Flowers</title>
        <tgroup cols="3">
          <colspec colname="c1" colnum="1" colwidth="1.0*"/>
          <colspec colname="c2" colnum="2" colwidth="1.0*"/>
          <colspec colname="c3" colnum="3" colwidth="1.0*"/>
          <thead>
            <row>
              <entry>Flower</entry>
              <entry>Type</entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>Chrysanthemum</entry>
              <entry>perennial</entry>
              <entry>well drained</entry>
            </row>
            <row>
              <entry>Gardenia</entry>
              <entry>perennial</entry>
            </row>
            <row>
              <entry>Gerbera</entry>
              <entry>annual</entry>
              <entry>sandy, well-drained</entry>
            </row>
            <row>
              <entry>Iris</entry>
            </row>
          </tbody>
        </tgroup>
      </table>
''')

results = select(root, 'min(.//row/count(entry))')

print(results)

results = select(root, 'min(.//row/count(entry))', parser=XPath3Parser)

print(results)

The first select using the default XPath 2 parser works fine and the output of the subsequent print is 1, but the following code fails with

Traceback (most recent call last):
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\elementpath-test1.py", line 45, in <module>
    results = select(root, 'min(.//row/count(entry))', parser=XPath3Parser)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\xpath_selectors.py", line 53, in select
    root_token = _parser.parse(path)
                 ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\xpath2\xpath2_parser.py", line 510, in parse
    root_token = super(XPath1Parser, self).parse(source)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\tdop.py", line 497, in parse
    root_token = self.expression()
                 ^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\tdop.py", line 622, in expression
    left = self.token.nud()
           ^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\xpath_tokens.py", line 1454, in nud
    self._items[k:] = self.parser.expression(5),
                      ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\tdop.py", line 625, in expression
    left = self.token.led(left)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\xpath1\_xpath1_operators.py", line 718, in led_child_or_descendant_path
    self[:] = left, self.parser.expression(75)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\tdop.py", line 622, in expression
    left = self.token.nud()
           ^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\xpath_tokens.py", line 1454, in nud
    self._items[k:] = self.parser.expression(5),
                      ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\tdop.py", line 622, in expression
    left = self.token.nud()
           ^^^^^^^^^^^^^^^^
  File "C:\Users\marti\PycharmProjects\Pyschematron-test1\.venv\Lib\site-packages\elementpath\xpath_tokens.py", line 1204, in nud
    raise self.error('XPST0017', msg) from None
elementpath.exceptions.ElementPathTypeError: 'entry' proxy function at line 1, column 18: [err:XPST0017] unknown function 'entry'
brunato commented 3 weeks ago

Hi, this is a problem of names collisions, that is implicit in XPath. The version 4.6.0 should fix this and other ambiguities, also with operators. thank you