diff --git a/elementpath/schema_proxy.py b/elementpath/schema_proxy.py
index b18b0f1..32a529b 100644
--- a/elementpath/schema_proxy.py
+++ b/elementpath/schema_proxy.py
@@ -226,7 +226,9 @@ class AbstractSchemaProxy(object):
class XMLSchemaProxy(AbstractSchemaProxy):
"""
- Schema proxy for the *xmlschema* library.
+ Schema proxy for the *xmlschema* library. It will be removed soon because
+ xmlschema v1.0.14 will includes an its own version of schema proxy that
+ uses a custom context implementation that recognizes circular references.
"""
def __init__(self, schema=None, base_element=None):
if schema is None:
diff --git a/elementpath/xpath1_parser.py b/elementpath/xpath1_parser.py
index 515fd1d..56c99d4 100644
--- a/elementpath/xpath1_parser.py
+++ b/elementpath/xpath1_parser.py
@@ -82,6 +82,8 @@ class XPath1Parser(Parser):
in the instance with the ones passed with the *namespaces* argument.
"""
+ schema = None # To simplify the schema bind checks in compatibility with XPath2Parser
+
def __init__(self, namespaces=None, variables=None, strict=True, *args, **kwargs):
super(XPath1Parser, self).__init__()
self.namespaces = self.DEFAULT_NAMESPACES.copy()
@@ -1026,12 +1028,18 @@ def evaluate(self, context=None):
@method(function('string-length', nargs=1))
def evaluate(self, context=None):
+ if self.parser.version == '1.0':
+ arg = self.get_argument(context, default_to_context=True, default='')
+ return len(self.string_value(arg))
return len(self.get_argument(context, default_to_context=True, default='', cls=string_base_type))
@method(function('normalize-space', nargs=1))
def evaluate(self, context=None):
- arg = self.get_argument(context, default_to_context=True, default='', cls=string_base_type)
+ if self.parser.version == '1.0':
+ arg = self.string_value(self.get_argument(context, default_to_context=True, default=''))
+ else:
+ arg = self.get_argument(context, default_to_context=True, default='', cls=string_base_type)
return ' '.join(arg.strip().split())
diff --git a/elementpath/xpath_context.py b/elementpath/xpath_context.py
index 9a948aa..7488880 100644
--- a/elementpath/xpath_context.py
+++ b/elementpath/xpath_context.py
@@ -233,4 +233,9 @@ class XPathContext(object):
class XPathSchemaContext(XPathContext):
- """Schema context class used during static analysis phase for matching tokens with schema types."""
+ """
+ The XPath dynamic context base class for schema bounded parsers. Use this class
+ as dynamic context for schema instances in order to perform a schema-based type
+ checking during the static analysis phase. Don't use this as dynamic context on
+ XML instances.
+ """
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 191e4d5..2a368e8 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -3,6 +3,6 @@ setuptools
tox
coverage
lxml
-xmlschema>=1.0.13
+xmlschema~=1.0.13
Sphinx
-e .
diff --git a/tests/test_schema_proxy.py b/tests/test_schema_proxy.py
index 9feba53..ec3d308 100644
--- a/tests/test_schema_proxy.py
+++ b/tests/test_schema_proxy.py
@@ -18,7 +18,7 @@ try:
except ImportError:
lxml_etree = None
-from elementpath import *
+from elementpath import AttributeNode, XPathContext, XPath2Parser, ElementPathTypeError
from elementpath.compat import PY3
from elementpath.namespaces import XML_LANG, XSD_NAMESPACE
@@ -27,6 +27,11 @@ try:
import xmlschema
except (ImportError, AttributeError):
xmlschema = None
+else:
+ try:
+ from xmlschema.xpath import XMLSchemaProxy # it works if xmlschema~=1.0.14
+ except ImportError:
+ from elementpath.schema_proxy import XMLSchemaProxy
try:
from tests import test_xpath2_parser
@@ -47,7 +52,8 @@ class XPath2ParserXMLSchemaTest(test_xpath2_parser.XPath2ParserTest):
def setUp(self):
self.schema_proxy = XMLSchemaProxy(self.schema)
- self.parser = XPath2Parser(namespaces=self.namespaces, schema=self.schema_proxy, variables=self.variables)
+ self.parser = XPath2Parser(namespaces=self.namespaces, schema=self.schema_proxy,
+ variables=self.variables)
def test_schema_proxy_init(self):
schema_src = """
@@ -60,16 +66,20 @@ class XPath2ParserXMLSchemaTest(test_xpath2_parser.XPath2ParserTest):
with self.assertRaises(TypeError):
XMLSchemaProxy(schema=schema_tree)
with self.assertRaises(TypeError):
- XMLSchemaProxy(schema=xmlschema.XMLSchema(schema_src), base_element=schema_tree)
+ XMLSchemaProxy(schema=xmlschema.XMLSchema(schema_src),
+ base_element=schema_tree)
with self.assertRaises(TypeError):
- XMLSchemaProxy(schema=xmlschema.XMLSchema(schema_src), base_element=schema_tree.getroot())
+ XMLSchemaProxy(schema=xmlschema.XMLSchema(schema_src),
+ base_element=schema_tree.getroot())
schema = xmlschema.XMLSchema(schema_src)
with self.assertRaises(ValueError):
XMLSchemaProxy(base_element=schema.elements['test_element'])
def test_xmlschema_proxy(self):
- context = XPathContext(root=self.etree.XML(''))
+ context = XPathContext(
+ root=self.etree.XML('')
+ )
self.wrong_name("schema-element(nil)")
self.wrong_name("schema-element(xs:string)")
@@ -82,7 +92,8 @@ class XPath2ParserXMLSchemaTest(test_xpath2_parser.XPath2ParserTest):
self.wrong_name("schema-attribute(xs:string)")
self.check_value("schema-attribute(xml:lang)", None)
self.check_value("schema-attribute(xml:lang)", context.item, context)
- self.check_tree("schema-attribute(xsi:schemaLocation)", '(schema-attribute (: (xsi) (schemaLocation)))')
+ self.check_tree("schema-attribute(xsi:schemaLocation)",
+ '(schema-attribute (: (xsi) (schemaLocation)))')
def test_get_type_api(self):
schema_proxy = XMLSchemaProxy()
@@ -135,7 +146,8 @@ class XPath2ParserXMLSchemaTest(test_xpath2_parser.XPath2ParserTest):
''')
- parser = XPath2Parser(namespaces=self.namespaces, schema=XMLSchemaProxy(schema, schema.elements['range']))
+ parser = XPath2Parser(namespaces=self.namespaces,
+ schema=XMLSchemaProxy(schema, schema.elements['range']))
token = parser.parse("@min le @max")
self.assertTrue(token.evaluate(context=XPathContext(self.etree.XML(''))))
self.assertFalse(token.evaluate(context=XPathContext(self.etree.XML(''))))
@@ -149,7 +161,8 @@ class XPath2ParserXMLSchemaTest(test_xpath2_parser.XPath2ParserTest):
''')
- parser = XPath2Parser(namespaces=self.namespaces, schema=XMLSchemaProxy(schema, schema.elements['range']))
+ parser = XPath2Parser(namespaces=self.namespaces,
+ schema=XMLSchemaProxy(schema, schema.elements['range']))
if PY3:
self.assertRaises(TypeError, parser.parse, '@min le @max')
else:
@@ -225,7 +238,8 @@ class XPath2ParserXMLSchemaTest(test_xpath2_parser.XPath2ParserTest):
self.assertEqual(token[0][1].xsd_type, schema.types['rangeType'])
self.assertEqual(token[1][0].xsd_type, schema.maps.types['{%s}integer' % XSD_NAMESPACE])
- context = XPathContext(root=self.etree.XML(''))
+ context = XPathContext(
+ root=self.etree.XML(''))
token = parser.parse("//b/@min lt //b/@max")
self.assertEqual(token[0][0][0].xsd_type, schema.types['rangeType'])
self.assertEqual(token[0][1][0].xsd_type, schema.maps.types['{%s}integer' % XSD_NAMESPACE])