mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-07-08 11:39:02 +00:00
xml: fix predicated xpath no-match incorrectly creating nodes (#12031)
* fix(xml): no-op when predicated xpath finds no match instead of creating nodes When using xpath like element[text()='old'] with value=new, a no-match due to the predicate not being satisfied incorrectly triggered node creation, corrupting the XML. Now treats predicate misses as a no-op. Fixes #8730 * changelog(xml): add fragment for PR #12031 * fix(xml): remove spurious test-unset-element-value include from main.yml That file belongs to a different branch and was accidentally dragged in during a stash conflict resolution. * feat(xml): add create_if_missing option to control node creation on value no-match Instead of implicitly creating nodes when value is set and xpath finds no match, expose create_if_missing (default true, preserving old behavior) so callers can opt into a silent no-op with create_if_missing=false. Fixes #8730
This commit is contained in:
parent
bb93811ea6
commit
15616be827
8 changed files with 139 additions and 4 deletions
|
|
@ -144,6 +144,13 @@ options:
|
|||
- This parameter requires O(xpath) to be set.
|
||||
type: bool
|
||||
default: false
|
||||
create_if_missing:
|
||||
description:
|
||||
- When using O(value) and the O(xpath) matches no nodes, create the node.
|
||||
- When set to V(false), a no-match is silently ignored instead of creating a new node.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: "13.0.0"
|
||||
requirements:
|
||||
- lxml >= 2.3.0
|
||||
notes:
|
||||
|
|
@ -673,11 +680,13 @@ def ensure_xpath_exists(module, tree, xpath, namespaces):
|
|||
finish(module, tree, xpath, namespaces, changed)
|
||||
|
||||
|
||||
def set_target_inner(module, tree, xpath, namespaces, attribute, value):
|
||||
def set_target_inner(module, tree, xpath, namespaces, attribute, value, create_if_missing=True):
|
||||
changed = False
|
||||
|
||||
try:
|
||||
if not is_node(tree, xpath, namespaces):
|
||||
if not create_if_missing:
|
||||
return changed
|
||||
changed = check_or_make_target(module, tree, xpath, namespaces)
|
||||
except Exception as e:
|
||||
missing_namespace = ""
|
||||
|
|
@ -722,8 +731,8 @@ def set_target_inner(module, tree, xpath, namespaces, attribute, value):
|
|||
return changed
|
||||
|
||||
|
||||
def set_target(module, tree, xpath, namespaces, attribute, value):
|
||||
changed = set_target_inner(module, tree, xpath, namespaces, attribute, value)
|
||||
def set_target(module, tree, xpath, namespaces, attribute, value, create_if_missing):
|
||||
changed = set_target_inner(module, tree, xpath, namespaces, attribute, value, create_if_missing)
|
||||
finish(module, tree, xpath, namespaces, changed)
|
||||
|
||||
|
||||
|
|
@ -895,6 +904,7 @@ def main():
|
|||
huge_tree=dict(type="bool", default=False),
|
||||
insertbefore=dict(type="bool", default=False),
|
||||
insertafter=dict(type="bool", default=False),
|
||||
create_if_missing=dict(type="bool", default=True),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
required_by=dict(
|
||||
|
|
@ -939,6 +949,7 @@ def main():
|
|||
huge_tree = module.params["huge_tree"]
|
||||
insertbefore = module.params["insertbefore"]
|
||||
insertafter = module.params["insertafter"]
|
||||
create_if_missing = module.params["create_if_missing"]
|
||||
|
||||
# Check if we have lxml 2.3.0 or newer installed
|
||||
if not HAS_LXML:
|
||||
|
|
@ -1014,7 +1025,7 @@ def main():
|
|||
|
||||
# Is the xpath target an attribute selector?
|
||||
if value is not None:
|
||||
set_target(module, doc, xpath, namespaces, attribute, value)
|
||||
set_target(module, doc, xpath, namespaces, attribute, value, create_if_missing)
|
||||
|
||||
# If an xpath was provided, we need to do something with the data
|
||||
if xpath is not None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue