Optimize qname_to_prefixed() and get_namespace() helpers
- use_empty optional argument added to qname_to_prefixed()
This commit is contained in:
parent
c075ff22e5
commit
6942be8ac9
|
@ -70,6 +70,9 @@ NAMESPACE_PATTERN = re.compile(r'{([^}]*)}')
|
|||
|
||||
|
||||
def get_namespace(name):
|
||||
if not name or name[0] != '{':
|
||||
return ''
|
||||
|
||||
try:
|
||||
return NAMESPACE_PATTERN.match(name).group(1)
|
||||
except (AttributeError, TypeError):
|
||||
|
|
|
@ -224,34 +224,38 @@ def local_name(qname):
|
|||
return qname
|
||||
|
||||
|
||||
def qname_to_prefixed(qname, namespaces):
|
||||
def qname_to_prefixed(qname, namespaces, use_empty=True):
|
||||
"""
|
||||
Transforms a fully qualified name into a prefixed name using a namespace map.
|
||||
Returns the *qname* argument if it's not a fully qualified name or if it has
|
||||
boolean value `False`.
|
||||
Maps a QName in extended format to a QName in prefixed format.
|
||||
Do not change local names and QNames in prefixed format.
|
||||
|
||||
:param qname: an extended QName or a local name.
|
||||
:param qname: a QName or a local name.
|
||||
:param namespaces: a map from prefixes to namespace URIs.
|
||||
:param use_empty: if `True` use the empty prefix for mapping.
|
||||
:return: a QName in prefixed format or a local name.
|
||||
"""
|
||||
if not qname:
|
||||
if not qname or qname[0] != '{':
|
||||
return qname
|
||||
|
||||
namespace = get_namespace(qname)
|
||||
for prefix, uri in sorted(filter(lambda x: x[1] == namespace, namespaces.items()), reverse=True):
|
||||
if not uri:
|
||||
return '%s:%s' % (prefix, qname) if prefix else qname
|
||||
elif prefix:
|
||||
return qname.replace('{%s}' % uri, '%s:' % prefix)
|
||||
else:
|
||||
return qname.replace('{%s}' % uri, '')
|
||||
prefixes = [x for x in namespaces if namespaces[x] == namespace]
|
||||
|
||||
if not prefixes:
|
||||
return qname
|
||||
elif prefixes[0]:
|
||||
return '%s:%s' % (prefixes[0], qname.split('}', 1)[1])
|
||||
elif len(prefixes) > 1:
|
||||
return '%s:%s' % (prefixes[1], qname.split('}', 1)[1])
|
||||
elif use_empty:
|
||||
return qname.split('}', 1)[1]
|
||||
else:
|
||||
return qname
|
||||
|
||||
|
||||
def qname_to_extended(qname, namespaces):
|
||||
"""
|
||||
Converts a QName in prefixed format or a local name to the extended QName format.
|
||||
Maps a QName in prefixed format or a local name to the extended QName format.
|
||||
Local names are mapped if *namespaces* has a not empty default namespace.
|
||||
|
||||
:param qname: a QName in prefixed format or a local name.
|
||||
:param namespaces: a map from prefixes to namespace URIs.
|
||||
|
|
|
@ -40,6 +40,9 @@ class TestHelpers(unittest.TestCase):
|
|||
self.assertEqual(get_namespace(XSD_SIMPLE_TYPE), XSD_NAMESPACE)
|
||||
self.assertEqual(get_namespace(''), '')
|
||||
self.assertEqual(get_namespace(None), '')
|
||||
self.assertEqual(get_namespace('{}name'), '')
|
||||
self.assertEqual(get_namespace('{ }name'), ' ')
|
||||
self.assertEqual(get_namespace('{ ns }name'), ' ns ')
|
||||
|
||||
def test_get_qname_functions(self):
|
||||
self.assertEqual(get_qname(XSD_NAMESPACE, 'element'), XSD_ELEMENT)
|
||||
|
@ -81,8 +84,21 @@ class TestHelpers(unittest.TestCase):
|
|||
self.assertEqual(qname_to_prefixed('', {}), '')
|
||||
|
||||
self.assertEqual(qname_to_prefixed('type', {'': XSI_NAMESPACE}), 'type')
|
||||
self.assertEqual(qname_to_prefixed('type', {'ns': ''}), 'ns:type')
|
||||
self.assertEqual(qname_to_prefixed('type', {'': ''}), 'type')
|
||||
self.assertEqual(qname_to_prefixed('{}type', {'': ''}), 'type')
|
||||
self.assertEqual(qname_to_prefixed('{}type', {'': ''}, use_empty=False), '{}type')
|
||||
|
||||
# Attention! in XML the empty namespace (that means no namespace) can be
|
||||
# associated only with empty prefix, so these cases should never happen.
|
||||
self.assertEqual(qname_to_prefixed('{}type', {'p': ''}), 'p:type')
|
||||
self.assertEqual(qname_to_prefixed('type', {'p': ''}), 'type')
|
||||
|
||||
self.assertEqual(qname_to_prefixed('{ns}type', {'': 'ns'}, use_empty=True), 'type')
|
||||
self.assertEqual(qname_to_prefixed('{ns}type', {'': 'ns'}, use_empty=False), '{ns}type')
|
||||
self.assertEqual(qname_to_prefixed('{ns}type', {'': 'ns', 'p': 'ns'}, use_empty=True), 'p:type')
|
||||
self.assertEqual(qname_to_prefixed('{ns}type', {'': 'ns', 'p': 'ns'}, use_empty=False), 'p:type')
|
||||
self.assertEqual(qname_to_prefixed('{ns}type', {'': 'ns', 'p': 'ns0'}, use_empty=True), 'type')
|
||||
self.assertEqual(qname_to_prefixed('{ns}type', {'': 'ns', 'p': 'ns0'}, use_empty=False), '{ns}type')
|
||||
|
||||
def test_get_xsd_annotation(self):
|
||||
elem = etree_element(XSD_SCHEMA)
|
||||
|
|
|
@ -15,6 +15,7 @@ from __future__ import unicode_literals
|
|||
|
||||
from ..compat import PY3, string_base_type
|
||||
from ..exceptions import XMLSchemaException, XMLSchemaWarning, XMLSchemaValueError
|
||||
from ..namespaces import get_namespace
|
||||
from ..qnames import qname_to_prefixed
|
||||
from ..etree import etree_tostring, etree_getpath
|
||||
from ..helpers import is_etree_element
|
||||
|
@ -317,11 +318,11 @@ class XMLSchemaChildrenValidationError(XMLSchemaValidationError):
|
|||
self.occurs = occurs
|
||||
self.expected = expected
|
||||
|
||||
tag = qname_to_prefixed(elem.tag, validator.namespaces)
|
||||
tag = qname_to_prefixed(elem.tag, validator.namespaces, use_empty=False)
|
||||
if index >= len(elem):
|
||||
reason = "The content of element %r is not complete." % tag
|
||||
else:
|
||||
child_tag = qname_to_prefixed(elem[index].tag, validator.namespaces)
|
||||
child_tag = qname_to_prefixed(elem[index].tag, validator.namespaces, use_empty=False)
|
||||
reason = "Unexpected child with tag %r at position %d." % (child_tag, index + 1)
|
||||
|
||||
if occurs and particle.is_missing(occurs):
|
||||
|
|
Loading…
Reference in New Issue