Skip to content

Commit d0df0b1

Browse files
committed
add support for processing instructions (that are under the root node)
1 parent fb10258 commit d0df0b1

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

lxml_parser.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@ class LocationAwareComment(etree.CommentBase):
4141
tag_pos = None
4242

4343

44+
class LocationAwareProcessingInstruction(etree.PIBase):
45+
tag_pos = None
46+
47+
4448
# http://stackoverflow.com/questions/36246014/lxml-use-default-class-element-lookup-and-treebuilder-parser-target-at-the-sam
4549
class LocationAwareXMLParser:
46-
RE_SPLIT_XML = re.compile('<!\[CDATA\[|\]\]>|[<>]')
50+
RE_SPLIT_XML = re.compile(r'<!\[CDATA\[|\]\]>|[<>]')
4751

4852
def __init__(self, position_offset = 0, **parser_options):
4953
def getLocation(index=None):
@@ -163,6 +167,13 @@ def element_end(self, tag, location=None):
163167
def text_data(self, data, location=None):
164168
self._text.append(data)
165169

170+
def pi(self, target, data, location=None):
171+
if self._most_recent is not None:
172+
self._flush()
173+
self._appendNode(self.create_pi(target, data))
174+
self._most_recent.tag_pos = location
175+
self._in_tail = True
176+
166177
def comment(self, text, location=None):
167178
if self._most_recent is not None:
168179
self._flush()
@@ -173,6 +184,9 @@ def comment(self, text, location=None):
173184
def create_comment(self, text):
174185
return LocationAwareComment(text)
175186

187+
def create_pi(self, target, data):
188+
return LocationAwareProcessingInstruction(target, data)
189+
176190
def _appendNode(self, node):
177191
if self._element_stack: # if we have anything on the stack
178192
self._element_stack[-1].append(node) # append the node as a child to the last/top element on the stack
@@ -206,7 +220,7 @@ def lxml_etree_parse_xml_string_with_location(xml_chunks, position_offset = 0, s
206220
def getNodeTagRange(node, position_type):
207221
"""Given a node and position type (open or close), return the node's position."""
208222
pos = None
209-
if isinstance(node, LocationAwareComment):
223+
if isinstance(node, LocationAwareComment) or isinstance(node, LocationAwareProcessingInstruction):
210224
pos = node.tag_pos
211225
else:
212226
pos = getattr(node, position_type + '_tag_pos')

sublime_lxml.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ def get_nodes_from_document(nodes):
105105
element = node.getparent() # get the parent
106106
if element is None: # some nodes are not actually part of the original document we parsed, for example when using the substring function. so there is no way to find the original node, and therefore the location
107107
continue
108+
elif isinstance(node, etree.PIBase):
109+
element = node
108110
elif isinstance(node, etree.CommentBase):
109111
element = node
110112
elif isinstance(node, etree.ElementBase):
@@ -154,7 +156,7 @@ def ensureTagNameEndPosIsSet(node, open_pos):
154156
if next_node is not None:
155157
text_end_pos = getNodeTagRegion(view, next_node, 'open').begin()
156158
yield sublime.Region(text_begin_pos, text_end_pos)
157-
elif isinstance(node, etree.CommentBase):
159+
elif isinstance(node, etree.CommentBase) or isinstance(node, etree.PIBase):
158160
yield open_pos
159161
elif attr_name is None or attribute_position_type is None or attribute_position_type in ('element', 'parent'):
160162
# position type 'open' <|name| attr1="test"></name> "Goto name in open tag"

xpath.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ def completions_axis_specifiers():
958958
return [(completion + '\taxis', completion + '::') for completion in completions]
959959

960960
def completions_node_types():
961-
completions = ['text', 'node', 'comment'] # 'processing-instruction' is also a valid XPath node type, but not parsed into an ElementTree, so useless to show it in suggestions/completions
961+
completions = ['text', 'node', 'comment', 'processing-instruction']
962962
return [(completion + '\tnode type', completion + '()') for completion in completions]
963963

964964
def completions_functions():

0 commit comments

Comments
 (0)