Best Python code snippet using localstack_python
xml_patch.py
Source:xml_patch.py
1#!/usr/bin/env python2# Copyright (c) 2012 The Chromium Authors. All rights reserved.3# Use of this source code is governed by a BSD-style license that can be4# found in the LICENSE file.5""" This module is a utility for applying an xml patch to an xml file.6The format of the patch is described in the documentation for7the patch_xml() function.8"""9import collections10import copy11import third_party.etree.ElementTree as ElementTree12def PatchXML(source_xml_tree, patch_xml_tree):13 """Applies a patch to the source xml and returns a new merged xml tree.14 Given a patch xml tree, it applies the patch to the source xml tree15 and returns the resulting modified xml tree.16 Patching is done by reading the patch_xml_tree for an element and then17 finding the in-order matching element in the source_xml_tree. Both elements18 are entered to look for matching sub-elements recursively.19 Patching occurs when a <PatchRemove> or <PatchAdd> element is encountered20 in the patch xml tree. For a remove operation, the first element in the21 source_xml_tree from the current read position that matches the contents of22 the <PatchRemove> element is removed. The read pointer is updated accordingly.23 For an add operation, the contents of the <PatchAdd> element is added at the24 current reading location.25 If for example, an add operation needs to be done after certain elements,26 the elements can be listed before the <PatchAdd> operation so that they are27 matched first before the add operation.28 Example:29 Source file:30 <a>31 <b></b>32 <c></c>33 </a>34 Patch file:35 <a>36 <b></b>37 <PatchAdd><zzz></zzz></PatchAdd>38 </a>39 Result:40 <a>41 <b></b>42 <zzz></zzz>43 <c></c>44 </a>45 Args:46 source_xml_tree: An ElementTree object with base xml to change.47 patch_xml_tree: An ElementTree object with xml to apply. See above notes48 for the xml structure of a patch.49 Returns:50 A new xml tree based on source with the patch applied.51 Raises:52 General Exception indicating a merge error has occured.53 """54 source = source_xml_tree.getroot()55 patch = patch_xml_tree.getroot()56 if not ElementMatch(source, patch):57 raise Exception('Root nodes do not match, cannot merge')58 return ElementTree.ElementTree(MergeElement(source, patch))59def MergeElement(source_elem, patch_elem):60 """Applies a single patch element to a single source element.61 The merge is applied recursively for sub-elements. See the documentation62 for patch_xml() for a description of how patching is done.63 Args:64 source_elem: An Element object with xml to change.65 patch_elem: An Element object with xml to apply.66 Returns:67 A new xml Element with the patch_elem applied to source_elem.68 Raises:69 General Exception indicating a merge error has occured.70 """71 assert ElementMatch(source_elem, patch_elem), 'Mismatched merge'72 # Create a new element by copying tags from source. Below we will merge73 # the subelements of source with the patch and put them in new_element.74 new_element = ElementTree.Element(source_elem.tag, source_elem.attrib)75 patch_children = list(patch_elem)76 patch_index = 077 remove_targets = collections.deque()78 find_target = None79 for source_child in source_elem:80 # If we have no current patch operation then read the next patch element.81 while (len(remove_targets) == 0 and find_target is None and82 patch_index < len(patch_children)):83 # PatchAdd operation.84 if IsPatchAddTag(patch_children[patch_index].tag):85 for addition in patch_children[patch_index]:86 new_element.append(copy.deepcopy(addition))87 # Start a remove operation by creating a list of elements to skip adding.88 elif IsPatchRemoveTag(patch_children[patch_index].tag):89 remove_targets = collections.deque(90 patch_children[patch_index])91 # Not an Add or Remove, must be a find target (find operation).92 else:93 find_target = patch_children[patch_index]94 patch_index += 195 # A remove operation means skipping adding the element to new_element.96 if (len(remove_targets) > 0 and97 ElementMatch(source_child, remove_targets[0])):98 remove_targets.popleft()99 # A matching find target means we must merge the sub-elements.100 elif find_target is not None and ElementMatch(source_child, find_target):101 merge = MergeElement(source_child, find_target)102 new_element.append(copy.deepcopy(merge))103 find_target = None104 # Otherwise this source element doesn't match any patch operations, add it.105 else:106 new_element.append(copy.deepcopy(source_child))107 # Raise exceptions if find/remove didn't finish before the end of the source.108 if find_target is not None:109 raise Exception('Find operation never matched:' + find_target.tag)110 elif len(remove_targets) != 0:111 raise Exception('Remove operation never matched: ' + remove_targets)112 # We may have more add operations after source has run empty:113 while patch_index < len(patch_children):114 if IsPatchAddTag(patch_children[patch_index].tag):115 for addition in patch_children[patch_index]:116 new_element.append(copy.deepcopy(addition))117 patch_index += 1118 else:119 raise Exception('Non-add operation attempted after source end. ' +120 'Tag: %s, Children %s' %121 (patch_children[patch_index].tag,122 list(patch_children[patch_index])))123 return new_element124def ElementMatch(elem1, elem2):125 return elem1.tag == elem2.tag and elem1.attrib == elem2.attrib126def IsPatchAddTag(tag):127 # We look at the end of the tag because we need to ignore the namespace.128 # Because the tag can be a sub-element of arbitrary elements it could inherit129 # any default namespace.130 return tag.endswith('PatchAdd')131def IsPatchRemoveTag(tag):132 # We look at the end of the tag because we need to ignore the namespace.133 # Because the tag can be a sub-element of arbitrary elements it could inherit134 # any default namespace....
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!