diff --git a/cumulusci/core/source_transforms/tests/test_transforms.py b/cumulusci/core/source_transforms/tests/test_transforms.py index 99230f2fe2..4aa66204b2 100644 --- a/cumulusci/core/source_transforms/tests/test_transforms.py +++ b/cumulusci/core/source_transforms/tests/test_transforms.py @@ -883,6 +883,25 @@ def test_xpath_replace_with_exp_and_index(task_context): zip_assert(builder, modified_zip_content) +def test_xpath_replace_with_exp_and_index_has_xmlns(task_context): + zip_content = { + Path( + "Foo.xml" + ): ' Everyday Italian Giada De Laurentiis 2005 30.00 Harry Potter J K. Rowling 2005 29.99 XQuery Kick Start James McGovern Per Bothner Kurt Cagle James Linn Vaidyanathan Nagarajan 2003 49.99 Learning XML Erik T. Ray 2003 39.95 ', + } + patterns = [ + {"xpath": "/bookstore/book[price>40]/author[2]", "replace": "Rich Author"} + ] + builder = create_builder(task_context, zip_content, patterns) + + modified_zip_content = { + Path( + "Foo.xml" + ): ' Everyday Italian Giada De Laurentiis 2005 30.00 Harry Potter J K. Rowling 2005 29.99 XQuery Kick Start James McGovern Rich Author Kurt Cagle James Linn Vaidyanathan Nagarajan 2003 49.99 Learning XML Erik T. Ray 2003 39.95 ', + } + zip_assert(builder, modified_zip_content) + + def test_xpath_replace_with_exp_and_index2(task_context): zip_content = { Path( diff --git a/cumulusci/core/source_transforms/transforms.py b/cumulusci/core/source_transforms/transforms.py index ab311b1456..d14ce196a7 100644 --- a/cumulusci/core/source_transforms/transforms.py +++ b/cumulusci/core/source_transforms/transforms.py @@ -2,7 +2,6 @@ import functools import io import os -import re import shutil import typing as T import zipfile @@ -416,24 +415,6 @@ def __init__(self, options: FindReplaceTransformOptions): self.options = options def process(self, zf: ZipFile, context: TaskContext) -> ZipFile: - # To handle xpath with namespaces, without - def transform_xpath(expression): - predicate_pattern = re.compile(r"\[.*?\]") - parts = expression.split("/") - transformed_parts = [] - - for part in parts: - if part: - predicates = predicate_pattern.findall(part) - tag = predicate_pattern.sub("", part) - transformed_part = '/*[local-name()="' + tag + '"]' - for predicate in predicates: - transformed_part += predicate - transformed_parts.append(transformed_part) - transformed_expression = "".join(transformed_parts) - - return transformed_expression - def process_file(filename: str, content: str) -> T.Tuple[str, str]: path = Path(filename) for spec in self.options.patterns: @@ -442,6 +423,7 @@ def process_file(filename: str, content: str) -> T.Tuple[str, str]: ): try: # See if the content is an xml file + content = content.replace(' xmlns="', ' xmlnamespace="') content_bytes = content.encode("utf-8") root = ET.fromstring(content_bytes) @@ -460,8 +442,7 @@ def process_file(filename: str, content: str) -> T.Tuple[str, str]: stack.extend(element) # Modify the element given by xpath elif spec.xpath: - transformed_xpath = transform_xpath(spec.xpath) - elements_to_replace = root.xpath(transformed_xpath) + elements_to_replace = root.xpath(spec.xpath) for element in elements_to_replace: element.text = spec.get_replace_string(context) @@ -469,7 +450,7 @@ def process_file(filename: str, content: str) -> T.Tuple[str, str]: content = ET.tostring( root, encoding="utf-8", xml_declaration=has_xml_declaration ).decode("utf-8") - + content = content.replace(' xmlnamespace="', ' xmlns="') except ET.XMLSyntaxError: if spec.find: content = content.replace(