Python脚本开发:基于祖辈节点属性修改XML的motions.z_neg属性
问题描述
我是编程和Python新手,提前感谢各位的耐心解答。我需要编写Python脚本,实现以下功能:当XML中的<line_support>节点的name属性包含'x-stiff'时,修改其后代<motions>节点的z_neg属性,且要对所有符合条件的<line_support>节点执行该操作。目前我无法正确关联<motions>节点对应的祖辈<line_support>节点,以下是我的尝试代码及XML示例:
尝试代码1
import xml.etree.ElementTree as et et.register_namespace('', 'urn:strusoft') model_path = '\\FEM\\floor1\\model_1.struxml' tree = et.parse(model_path) root = tree.getroot() for support2 in root[0].iter("{urn:strusoft}motions"): print(support2.tag, support2.attrib)
尝试代码2
for support in root.findall(".//motions/../../../[@name='x-stiff']/"): print(support.attrib)
XML示例
<database xmlns="urn:strusoft" struxml_version="01.00.000" source_software="FEM-Design 22.00.001" start_time="1970-01-01T00:00:00.000" end_time="2023-03-17T10:21:10.000" guid="e2686f2d-4156-4971-8d86-5ef16a5c2169" convertid="00000000-0000-0000-0000-000000000000" standard="EC" country="S"> <entities> <supports> <line_support guid="22938a5b-b5f2-48b0-8ab0-182dfcad415e" last_change="2023-03-16T13:13:57.000" action="added" name="S.1"> <group> <local_x x="1" y="2.58195798774967E-12" z="0" /> <local_y x="-2.58195798774967E-12" y="1" z="0" /> <rigidity> <motions x_neg="0" x_pos="0" y_neg="0" y_pos="0" z_neg="5" z_pos="10000000" /> <rotations x_neg="0" x_pos="0" y_neg="0" y_pos="0" z_neg="0" z_pos="0" /> </rigidity> </group> <edge type="line"> <point x="24.6263818250883" y="-8.80836202657059" z="0" /> <point x="28.6628090737921" y="-8.80836202656017" z="0" /> <normal x="-2.58195798774967E-12" y="1" z="0" /> </edge> <normal x="0" y="0" z="1" /> </line_support> <line_support guid="d666b23d-df57-4f3d-b950-06fa4fc3227a" last_change="2023-03-16T13:14:12.000" action="added" name="S.2"> <group> <local_x x="0" y="-1" z="0" /> <local_y x="1" y="0" z="0" /> <rigidity> <motions x_neg="0" x_pos="0" y_neg="0" y_pos="0" z_neg="5" z_pos="10000000" /> <rotations x_neg="0" x_pos="0" y_neg="0" y_pos="0" z_neg="0" z_pos="0" /> </rigidity> </group> <edge type="line"> <point x="28.6628090737918" y="-14.4898620056551" z="0" /> <point x="28.6628090737921" y="-19.081361992569" z="0" /> <normal x="1" y="0" z="0" /> </edge> <normal x="0" y="0" z="1" /> </line_support> <line_support guid="21cf4052-e4ba-414d-a7ee-c78ecef2a3ff" last_change="2023-03-17T10:20:54.000" action="added" name="x-stiff.1"> <group> <local_x x="1" y="0" z="0" /> <local_y x="0" y="1" z="0" /> <rigidity> <motions x_neg="100000" x_pos="100000" y_neg="0" y_pos="0" z_neg="11" z_pos="10000000" /> <rotations x_neg="0" x_pos="0" y_neg="0" y_pos="0" z_neg="0" z_pos="0" /> </rigidity> </group> <edge type="line"> <point x="9.18988193734352" y="-12.244862026923" z="0" /> <point x="12.4263090828062" y="-12.2448620269228" z="0" /> <normal x="0" y="1" z="0" /> </edge> <normal x="0" y="0" z="1" /> </line_support> <line_support guid="c8d5eed1-302b-45b4-a943-0ad8202f2d78" last_change="2023-03-17T10:20:54.000" action="added" name="x-stiff.2"> <group> <local_x x="1" y="0" z="0" /> <local_y x="0" y="1" z="0" /> <rigidity> <motions x_neg="100000" x_pos="100000" y_neg="0" y_pos="0" z_neg="5" z_pos="10000000" /> <rotations x_neg="0" x_pos="0" y_neg="0" y_pos="0" z_neg="0" z_pos="0" /> </rigidity> </group> <edge type="line"> <point x="22.1863819301654" y="-8.80836202657082" z="0" /> <point x="24.6263818250883" y="-8.80836202657059" z="0" /> <normal x="0" y="1" z="0" /> </edge> <normal x="0" y="0" z="1" /> </line_support> <line_support guid="c61c91cc-ef02-49bf-9b94-19df5db97e04" last_change="2023-03-17T10:20:54.000" action="added" name="x-stiff.3"> <group> <local_x x="1" y="0" z="0" /> <local_y x="0" y="1" z="0" /> <rigidity> <motions x_neg="100000" x_pos="100000" y_neg="0" y_pos="0" z_neg="5" z_pos="10000000" /> <rotations x_neg="0" x_pos="0" y_neg="0" y_pos="0" z_neg="0" z_pos="0" /> </rigidity> </group> <edge type="line"> <point x="25.4263819283295" y="-12.244862026923" z="0" /> <point x="28.6628090737921" y="-12.2448620269228" z="0" /> <normal x="0" y="1" z="0" /> </edge> <normal x="0" y="0" z="1" /> </line_support> </supports> </entities> <end /> </database>
解决方案
你的问题核心在于两点:
- XML存在默认命名空间,使用XPath时未正确处理,导致节点匹配失败
- 尝试代码2的XPath路径逻辑错误,无法正确关联祖辈与后代节点
以下是修正后的完整代码,附带关键说明:
import xml.etree.ElementTree as et # 注册命名空间,避免保存XML时丢失命名空间声明 et.register_namespace('', 'urn:strusoft') # 定义命名空间映射,简化XPath写法 ns = {'ss': 'urn:strusoft'} # 使用r前缀避免路径反斜杠转义问题 model_path = r'\\FEM\\floor1\\model_1.struxml' tree = et.parse(model_path) root = tree.getroot() # 1. 筛选所有name属性包含'x-stiff'的line_support节点 for line_support in root.findall('.//ss:line_support[contains(@name, "x-stiff")]', ns): # 2. 在当前line_support节点内部查找后代motions节点 motions_node = line_support.find('.//ss:motions', ns) if motions_node is not None: # 修改z_neg属性,这里示例设为20,可替换为你需要的值 motions_node.set('z_neg', '20') print(f"已修改节点 {line_support.get('name')} 下的motions.z_neg属性") # 保存修改后的XML文件 tree.write(model_path, encoding='utf-8', xml_declaration=True) print("所有符合条件的节点修改完成,文件已保存")
关键细节说明
- 命名空间处理:XML根节点的
xmlns="urn:strusoft"定义了默认命名空间,所有子节点都属于该命名空间。必须通过命名空间映射ns来指定节点,否则无法匹配到目标元素。 - 精准节点关联:先定位符合条件的
line_support节点,再在该节点内部查找motions,确保修改的是对应祖辈下的后代节点,不会出现关联错误。 - 属性匹配逻辑:使用
contains(@name, "x-stiff")实现模糊匹配,符合你“name属性包含x-stiff”的需求,比精确匹配更灵活。 - 路径转义:文件路径用
r前缀可以避免反斜杠被解析为转义字符,减少路径错误。
内容的提问来源于stack exchange,提问作者Thorsson
相关产品推荐
相关产品推荐

