11# encoding: utf-8
22
3- """
4- Parser for Compact XML Expression Language (CXEL) ('see-ex-ell'), a compact
5- XML specification language I made up that's useful for producing XML element
6- trees suitable for unit testing.
3+ """Parser for Compact XML Expression Language (CXEL) ('see-ex-ell').
4+
5+ CXEL is a compact XML specification language I made up that's useful for producing XML
6+ element trees suitable for unit testing.
77"""
88
9- from __future__ import print_function
9+ from __future__ import absolute_import , division , print_function , unicode_literals
1010
1111from pyparsing import (
12- alphas , alphanums , Combine , dblQuotedString , delimitedList , Forward ,
13- Group , Literal , Optional , removeQuotes , stringEnd , Suppress , Word
12+ alphas ,
13+ alphanums ,
14+ Combine ,
15+ dblQuotedString ,
16+ delimitedList ,
17+ Forward ,
18+ Group ,
19+ Literal ,
20+ Optional ,
21+ removeQuotes ,
22+ stringEnd ,
23+ Suppress ,
24+ Word ,
1425)
1526
1627from docx .oxml import parse_xml
@@ -105,16 +116,25 @@ def is_root(self, value):
105116 self ._is_root = bool (value )
106117
107118 @property
108- def nspfx (self ):
119+ def local_nspfxs (self ):
109120 """
110- The namespace prefix of this element, the empty string (``''``) if
111- the tag is in the default namespace.
121+ The namespace prefixes local to this element, both on the tagname and
122+ all of its attributes. An empty string (``''``) is used to represent
123+ the default namespace for an element tag having no prefix.
112124 """
113- tagname = self ._tagname
114- idx = tagname .find (':' )
115- if idx == - 1 :
116- return ''
117- return tagname [:idx ]
125+ def nspfx (name , is_element = False ):
126+ idx = name .find (':' )
127+ if idx == - 1 :
128+ return '' if is_element else None
129+ return name [:idx ]
130+
131+ nspfxs = [nspfx (self ._tagname , True )]
132+ for name , val in self ._attrs :
133+ pfx = nspfx (name )
134+ if pfx is None or pfx in nspfxs or pfx == "xml" :
135+ continue
136+ nspfxs .append (pfx )
137+ return nspfxs
118138
119139 @property
120140 def nspfxs (self ):
@@ -129,7 +149,7 @@ def merge(seq, seq_2):
129149 continue
130150 seq .append (item )
131151
132- nspfxs = [ self .nspfx ]
152+ nspfxs = self .local_nspfxs
133153 for child in self ._children :
134154 merge (nspfxs , child .nspfxs )
135155 return nspfxs
@@ -223,12 +243,12 @@ def grammar():
223243
224244 # np:tagName ---------------------------------
225245 nspfx = Word (alphas )
226- local_name = Word (alphas )
246+ local_name = Word (alphanums )
227247 tagname = Combine (nspfx + colon + local_name )
228248
229249 # np:attr_name=attr_val ----------------------
230250 attr_name = Word (alphas + ':' )
231- attr_val = Word (alphanums + ' -.% ' )
251+ attr_val = Word (alphanums + ' %-./:_ ' )
232252 attr_def = Group (attr_name + equal + attr_val )
233253 attr_list = open_brace + delimitedList (attr_def ) + close_brace
234254
0 commit comments