Skip to content

Commit

Permalink
Getting ready to upload to Pypi
Browse files Browse the repository at this point in the history
  • Loading branch information
Erwin Kaats committed Oct 23, 2021
1 parent 193ae0c commit 672bd42
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 14 deletions.
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Parse XPATH 3.1 using Pyparsing
XPath (XML Path Language) is a query language for selecting nodes from an XML document.
In addition, XPath may be used to compute values (e.g., strings, numbers, or Boolean values) from the content of an XML document.
XPath is supported by the World Wide Web Consortium (W3C).
In addition, XPath is used to compute values (e.g., strings, numbers, or Boolean values) from the content of an XML document.
XPath is maintained by the World Wide Web Consortium (W3C).

[Pyparsing](https://github.com/pyparsing/pyparsing) is a parsing module used to construct grammar in Python.
XPyth uses Pyparsing to parse XPath strings, and offers an additional abstraction layer.
XPyth-parser uses Pyparsing to parse XPath strings, and offers an additional abstraction layer.

## Status
This library is an attempt to create a parser which can be used both to query XML documents,
Expand All @@ -13,12 +13,16 @@ The original plan was to support both options. However, XPath 3.1 is not widely
Parsing XPath 3.1 on a grammar level should still be supported, but not all information may be available when using
the abstraction layer. Most importantly, there will be [XPath functions](https://www.w3.org/2005/xpath-functions/) missing.

Dealing with dynamic contexts (i.e., parsing XML as Parser.xml will be done using LXML for now).
Dealing with dynamic contexts (i.e., parsing XML as Parser.xml will be done using LXML for now).
In a way, XPyth-parser is at the present moment a fancy wrapper around LXML, in order to support some XPath 2.0+ functionality.

### Alternatives
For most use cases, there will be (better) alternatives to this project. [LXML](https://lxml.de/) is Pythonic binding
for the C libraries libxml2 and libxslt. If only XPath 1.0 is needed, LXML will be a better solution.

### Requirements
xpyth-parser depends on LXML, PyParsing. For parsing dates we use Isodate.

## Goals
This project started out with a specific goal:
to parse [XBRL formula](https://specifications.xbrl.org/work-product-index-formula-formula-1.0.html) tests.
Expand All @@ -27,15 +31,19 @@ Because of this, the author of this library is focussing on correctly interpreti

# Examples

from xpyth_parser.parse import Parser
count = Parser("count(1,2,3)")

from xpyth_parser.parse import Parser
count = Parser("count(1,2,3)").run()
print(count) -> 3


This will give a wrapper class which contains the resolved syntax tree in count.XPath and the answer in count.resolved_answer

# Parsing only
It is also possible to only parse the string, but not try to resolve the static and dynamic context
count = Parser("count(1,2,3), no_resolve=True")

count.xpath will be the full syntax tree, instead of having functions processed and contexts applied.
count.run() will resolve the expression as if no_resolve=False. contexts might need to be passed to the object beforehand.
count = Parser("count(1,2,3), no_resolve=True")

`count.xpath` will be the full syntax tree, instead of having functions processed and contexts applied.
`count.run()` will resolve the expression as if no_resolve=False. contexts might need to be passed to the object beforehand.

5 changes: 3 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = xpyth_31_parser
version = 0.0.7
name = xpyth_parser
version = 0.0.9
author = Erwin Kaats
author_email = [email protected]
description = An XPath 3.1 Parser
Expand All @@ -19,6 +19,7 @@ package_dir =
packages = find:
python_requires = >=3.6
install_requires =
lxml
pyparsing
isodate

Expand Down
18 changes: 16 additions & 2 deletions src/xpyth_parser/grammar/expressions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import functools
import logging
import operator
import types

import pyparsing
from pyparsing import (
Expand Down Expand Up @@ -261,7 +261,21 @@ def resolve_fn(fn):

if isinstance(rootexpr, functools.partial):
# Main node is a Function. Resolve this and add the answer to the Syntax Tree.
return rootexpr()
# return rootexpr()
function_outcome = rootexpr()
if isinstance(function_outcome, types.GeneratorType):
answers = []
for ans in function_outcome:
# todo: try to figure out if Functions should be yielding (generator) or returning.
# I'd say yield, because "fn:number(1 to 100)[. mod 5 eq 0]" should be a legal expression
# where 1 to 100 is cast as a number, and 'fed' through the predidicate filtering.
answers.append(ans)
return answers


else:
return function_outcome

# return resolve_fn(rootexpr)

elif isinstance(rootexpr, Parameter):
Expand Down
2 changes: 1 addition & 1 deletion src/xpyth_parser/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def __init__(
:param parseAll: Boolean passed to PyParsing. If set to true, Parsing will fail if any part of the string is not understood.
:param variable_map: Dict of variables which Parameters can be mapped to.
:param xml: Byte string of an XML object to be parsed
:param no_resolve: If set to True, only grammar is parsed but the expression is not resolved.
:param no_resolve: If set to True, only grammar is parsed but the expression is not resolved. This can be used for debugging.
For example:
parsed_expr = Parser("(1 + 2) = (2 + 1)")
Expand Down

0 comments on commit 672bd42

Please sign in to comment.