def _buildMetadata(self, xpath, metadata = {}): parentXpath = xpath[:xpath.rfind("/")] childXpath = xpath[xpath.rfind("/") + 1:] if len(parentXpath) > 0: try: metadata[parentXpath].append(childXpath) except: metadata[parentXpath] = [childXpath] attributes = None next = iter(ElementPath.xpath_tokenizer(childXpath)).next while 1: try: token = next() if token[0] == "[": attributes = self._transformAttr(next, token) except StopIteration: break if attributes is not None: childXpath = xpath[:xpath.rfind("[")] return childXpath, attributes
def iterfind(self, path, namespaces=None): # compile selector pattern if path[-1:] == "/": path = path + "*" # implicit all (FIXME: keep this?) try: selector = ElementPath._cache[path] except KeyError: if len(ElementPath._cache) > 100: ElementPath._cache.clear() if path[:1] == "/": raise SyntaxError("cannot use absolute path on element") it = iter(ElementPath.xpath_tokenizer(path, namespaces)) next_ = lambda: next(it) token = next_() selector = [] while 1: try: selector.append(ElementPath.ops[token[0]](next_, token)) except StopIteration: raise SyntaxError("invalid path") try: token = next_() if token[0] == "/": token = next_() except StopIteration: break ElementPath._cache[path] = selector # execute selector pattern result = [self] context = self._SelectorContext(self) for select in selector: result = select(context, result) return result
def _buildMetadata(self, xpath, metadata={}): parentXpath = xpath[:xpath.rfind("/")] childXpath = xpath[xpath.rfind("/") + 1:] if len(parentXpath) > 0: try: metadata[parentXpath].append(childXpath) except: metadata[parentXpath] = [childXpath] attributes = None next = iter(ElementPath.xpath_tokenizer(childXpath)).next while 1: try: token = next() if token[0] == "[": attributes = self._transformAttr(next, token) except StopIteration: break if attributes is not None: childXpath = xpath[:xpath.rfind("[")] return childXpath, attributes
def test_predicate(self): """Test predicate addition """ element_test = ET.Element("test") element_temp = ET.Element("test") element_temp.text = "Hey" element_temp.set("val", "8") ET.SubElement(element_temp, "ins") token_iter = EP.xpath_tokenizer("@val=8]") xmlconfigparse.add_predicate(token_iter, element_test) token_iter = EP.xpath_tokenizer("text()=Hey]") xmlconfigparse.add_predicate(token_iter, element_test) token_iter = EP.xpath_tokenizer("ins/]") xmlconfigparse.add_predicate(token_iter, element_test) element_temp_string = ET.tostring(element_temp) element_test_string = ET.tostring(element_test) self.assertEqual( element_test_string, element_temp_string, msg="Unexpected string returned" )
def test_elementinset(self): """Test method insert subelements """ element_test = ET.Element("test") element_temp = ET.Element("test") new_temp = ET.SubElement(element_temp, "new") ET.SubElement(new_temp, "insert") token_iter = EP.xpath_tokenizer("new/insert") xmlconfigparse.elementinsert(token_iter, element_test) element_temp_string = ET.tostring(element_temp) element_test_string = ET.tostring(element_test) self.assertEqual( element_test_string, element_temp_string, msg="Unexpected string returned" )
def xmlinsert(xpath, xmlfile, tag=".", findall=False): """Inserts elements from an xpath refs: xml.etree.ElementPath https://github.com/python/cpython/blob/3.7/Lib/xml/etree/ElementPath.py Args: xpath (str): xml elements separated by back slash (no whitespace outside of attributes) xmlfile (str): path to xml file; created if it doesn't exist tag (str): xml element to serve as parent (/ or . = root) findall (bool): If true finds all matching times matching tag and inserts xml elements from xpaths after deepest member Returns: str: location of updated xml file Notes: xpath (str): expects paths which only descend. And supports the following symbols in xpath /()[]@= excludes (//, ..) ex. a[bar=/hello/world]/be[text()="there"]/can[@nope=there]/day tag (str): used by implementation of Elementree's iterfind function so see xml.etree.elementree for limitations. """ # import xml and convert to element tree = ET.parse(xmlfile) root = tree.getroot() # no absolute paths if xpath[0] == "/": raise SyntaxError("Can't create another root directory in an xml file") token_iter = EP.xpath_tokenizer(xpath) # check recursive if findall: for element in root.iterfind(tag): elementinsert(token_iter, element) else: # if tag defined root replaced elementinsert(token_iter, root.find(tag)) tree.write(xmlfile) return xmlfile
def ExportXML(self, filename = None): """ Build element tree from xpaths """ # Tree root node root = None #Map to store xpath and ElementXpath self.mapparentelem = {} ''' Select all rows of db to export ''' for xpath in self.Iterators('/'): #Is attribute xpath? /a/b/c@name => attr name attr_xpath = False try: value = str(self.Read(xpath)) except SystemError, e: print "Cannot read [%s], error %s" % (xpath,str(e)) continue next = iter(ElementPath.xpath_tokenizer(xpath)).next #For each leaf node on xpath current_elemment = root #parent xpath parent_xpath = None #current xpath token current_xpath = None while 1: try: token = next() if token[0] == "/": token = next() #Ignore attribue element (xpath=//sg/@name) if token[0] == "@": attr_xpath = True continue index = xpath.rfind("/%s" %token[1]) if index >= 0: parent_xpath = "%s" %(xpath[:index]) #Get xpath assume suffix is leaf next_index = xpath.find("/", len(parent_xpath) + 1) if next_index>0: current_xpath = xpath[0:next_index] else: #Last leaf current_xpath = xpath if root is None: root = ET.Element(key_to_xml(token[1])) current_elemment = root self.mapparentelem["/%s" %token[1]] = current_elemment else: current_elemment = self._buildNode(current_xpath) elif token[0] == "[": attributes = self._transformAttr(next, token) if len(attributes) > 0: current_elemment.attrib = attributes except StopIteration: break if attr_xpath == False: current_elemment.text = value
def ExportXML(self, filename=None): """ Build element tree from xpaths """ # Tree root node root = None #Map to store xpath and ElementXpath self.mapparentelem = {} ''' Select all rows of db to export ''' for xpath in self.Iterators('/'): #Is attribute xpath? /a/b/c@name => attr name attr_xpath = False try: value = str(self.Read(xpath)) except SystemError, e: print "Cannot read [%s], error %s" % (xpath, str(e)) continue next = iter(ElementPath.xpath_tokenizer(xpath)).next #For each leaf node on xpath current_elemment = root #parent xpath parent_xpath = None #current xpath token current_xpath = None while 1: try: token = next() if token[0] == "/": token = next() #Ignore attribue element (xpath=//sg/@name) if token[0] == "@": attr_xpath = True continue index = xpath.rfind("/%s" % token[1]) if index >= 0: parent_xpath = "%s" % (xpath[:index]) #Get xpath assume suffix is leaf next_index = xpath.find("/", len(parent_xpath) + 1) if next_index > 0: current_xpath = xpath[0:next_index] else: #Last leaf current_xpath = xpath if root is None: root = ET.Element(key_to_xml(token[1])) current_elemment = root self.mapparentelem["/%s" % token[1]] = current_elemment else: current_elemment = self._buildNode( current_xpath) elif token[0] == "[": attributes = self._transformAttr(next, token) if len(attributes) > 0: current_elemment.attrib = attributes except StopIteration: break if attr_xpath == False: current_elemment.text = value