Skip to content

Commit 5ec3ac1

Browse files
author
Steve Canny
committed
oxml: extract NamespacePrefixedTag to docx.oxml.ns
And added unit tests for NamespacePrefixedTag
1 parent 8af48cf commit 5ec3ac1

3 files changed

Lines changed: 109 additions & 51 deletions

File tree

docx/oxml/ns.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,54 @@
1919
'Drawing'),
2020
'xml': ('http://www.w3.org/XML/1998/namespace')
2121
}
22+
23+
24+
class NamespacePrefixedTag(str):
25+
"""
26+
Value object that knows the semantics of an XML tag having a namespace
27+
prefix.
28+
"""
29+
def __new__(cls, nstag, *args):
30+
return super(NamespacePrefixedTag, cls).__new__(cls, nstag)
31+
32+
def __init__(self, nstag):
33+
self._pfx, self._local_part = nstag.split(':')
34+
self._ns_uri = nsmap[self._pfx]
35+
36+
@property
37+
def clark_name(self):
38+
return '{%s}%s' % (self._ns_uri, self._local_part)
39+
40+
@property
41+
def local_part(self):
42+
"""
43+
Return the local part of the tag as a string. E.g. 'foobar' is
44+
returned for tag 'f:foobar'.
45+
"""
46+
return self._local_part
47+
48+
@property
49+
def nsmap(self):
50+
"""
51+
Return a dict having a single member, mapping the namespace prefix of
52+
this tag to it's namespace name (e.g. {'f': 'http://foo/bar'}). This
53+
is handy for passing to xpath calls and other uses.
54+
"""
55+
return {self._pfx: self._ns_uri}
56+
57+
@property
58+
def nspfx(self):
59+
"""
60+
Return the string namespace prefix for the tag, e.g. 'f' is returned
61+
for tag 'f:foobar'.
62+
"""
63+
return self._pfx
64+
65+
@property
66+
def nsuri(self):
67+
"""
68+
Return the namespace URI for the tag, e.g. 'http://foo/bar' would be
69+
returned for tag 'f:foobar' if the 'f' prefix maps to
70+
'http://foo/bar' in nsmap.
71+
"""
72+
return self._ns_uri

docx/oxml/shared.py

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,63 +12,13 @@
1212

1313
from . import oxml_parser
1414
from .exceptions import ValidationError
15-
from .ns import nsmap
15+
from .ns import NamespacePrefixedTag, nsmap
1616

1717

1818
# ===========================================================================
1919
# utility functions
2020
# ===========================================================================
2121

22-
class NamespacePrefixedTag(str):
23-
"""
24-
Value object that knows the semantics of an XML tag having a namespace
25-
prefix.
26-
"""
27-
def __new__(cls, nstag, *args):
28-
return super(NamespacePrefixedTag, cls).__new__(cls, nstag)
29-
30-
def __init__(self, nstag):
31-
self._pfx, self._local_part = nstag.split(':')
32-
self._ns_uri = nsmap[self._pfx]
33-
34-
@property
35-
def clark_name(self):
36-
return '{%s}%s' % (self._ns_uri, self._local_part)
37-
38-
@property
39-
def local_part(self):
40-
"""
41-
Return the local part of the tag as a string. E.g. 'foobar' is
42-
returned for tag 'f:foobar'.
43-
"""
44-
return self._local_part
45-
46-
@property
47-
def nsmap(self):
48-
"""
49-
Return a dict having a single member, mapping the namespace prefix of
50-
this tag to it's namespace name (e.g. {'f': 'http://foo/bar'}). This
51-
is handy for passing to xpath calls and other uses.
52-
"""
53-
return {self._pfx: self._ns_uri}
54-
55-
@property
56-
def nspfx(self):
57-
"""
58-
Return the string namespace prefix for the tag, e.g. 'f' is returned
59-
for tag 'f:foobar'.
60-
"""
61-
return self._pfx
62-
63-
@property
64-
def nsuri(self):
65-
"""
66-
Return the namespace URI for the tag, e.g. 'http://foo/bar' would be
67-
returned for tag 'f:foobar' if the 'f' prefix maps to
68-
'http://foo/bar' in nsmap.
69-
"""
70-
return self._ns_uri
71-
7222

7323
def nsdecls(*prefixes):
7424
return ' '.join(['xmlns:%s="%s"' % (pfx, nsmap[pfx]) for pfx in prefixes])

tests/oxml/test_ns.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Test suite for docx.oxml.ns
5+
"""
6+
7+
from __future__ import absolute_import, print_function, unicode_literals
8+
9+
import pytest
10+
11+
from docx.oxml.ns import NamespacePrefixedTag
12+
13+
14+
class DescribeNamespacePrefixedTag(object):
15+
16+
def it_behaves_like_a_string_when_you_want_it_to(self, nsptag):
17+
s = '- %s -' % nsptag
18+
assert s == '- a:foobar -'
19+
20+
def it_knows_its_clark_name(self, nsptag, clark_name):
21+
assert nsptag.clark_name == clark_name
22+
23+
def it_knows_its_local_part(self, nsptag, local_part):
24+
assert nsptag.local_part == local_part
25+
26+
def it_can_compose_a_single_entry_nsmap_for_itself(
27+
self, nsptag, namespace_uri_a):
28+
expected_nsmap = {'a': namespace_uri_a}
29+
assert nsptag.nsmap == expected_nsmap
30+
31+
def it_knows_its_namespace_prefix(self, nsptag):
32+
assert nsptag.nspfx == 'a'
33+
34+
def it_knows_its_namespace_uri(self, nsptag, namespace_uri_a):
35+
assert nsptag.nsuri == namespace_uri_a
36+
37+
# fixtures -------------------------------------------------------
38+
39+
@pytest.fixture
40+
def clark_name(self, namespace_uri_a, local_part):
41+
return '{%s}%s' % (namespace_uri_a, local_part)
42+
43+
@pytest.fixture
44+
def local_part(self):
45+
return 'foobar'
46+
47+
@pytest.fixture
48+
def namespace_uri_a(self):
49+
return 'http://schemas.openxmlformats.org/drawingml/2006/main'
50+
51+
@pytest.fixture
52+
def nsptag(self, nsptag_str):
53+
return NamespacePrefixedTag(nsptag_str)
54+
55+
@pytest.fixture
56+
def nsptag_str(self, local_part):
57+
return 'a:%s' % local_part

0 commit comments

Comments
 (0)