解决XPath评估节点过多问题:将xjc类名转为驼峰式
解决XJC绑定文件生成时XPath匹配过多节点的问题
问题原因
你遇到的错误是因为XSD中存在多个同名的element节点(比如CONTEXT-COMPONENT-REF在16个不同位置定义),而脚本中生成的XPath仅通过@name匹配,会命中所有同名节点,JAXB要求每个绑定规则必须唯一匹配单个节点,因此报错。
解决方案:生成节点的唯一XPath
修改Python脚本,为每个节点生成唯一的层级路径XPath,确保绑定规则只指向单个节点。
1. 添加生成唯一XPath的函数
这个函数会遍历节点的父层级,结合同层级节点的索引生成精确路径:
def generate_unique_xpath(node, root): parts = [] current = node while current is not None and current != root: # 提取不带命名空间的标签名 tag = current.tag.split('}')[-1] if '}' in current.tag else current.tag # 计算同层级同标签节点的索引(XPath索引从1开始) parent = current.getparent() siblings = parent.findall(current.tag) if parent else [] if len(siblings) > 1: index = siblings.index(current) + 1 parts.append(f"{tag}[{index}]") else: parts.append(tag) current = parent # 反转路径,从根节点到当前节点 parts.reverse() # 拼接根节点标签 root_tag = root.tag.split('}')[-1] if '}' in root.tag else root.tag parts.insert(0, root_tag) return '/'.join(parts)
2. 修改绑定生成函数
替换原来的unique_xpath生成逻辑,使用上面的函数生成精确路径:
def generate_bindings_for_node(node_type, xpath, root, namespaces): for node in root.findall(xpath, namespaces): name = node.get('name') if name: # 生成唯一XPath node_unique_path = generate_unique_xpath(node, root) # 补充xsd命名空间前缀 unique_xpath = f".//xsd:{node_unique_path.replace('/', '/xsd:')}" # 创建绑定节点 bindings = ET.SubElement(bindings_root, 'jaxb:bindings', { 'node': unique_xpath }) ET.SubElement(bindings, node_type, { 'name': to_camel_case(name) })
额外优化:命名空间声明
确保脚本中正确声明JAXB和XSD的命名空间,避免解析错误:
namespaces = { 'xsd': 'http://www.w3.org/2001/XMLSchema', 'jaxb': 'http://java.sun.com/xml/ns/jaxb' } ET.register_namespace('jaxb', namespaces['jaxb'])
这样生成的绑定文件中,每个jaxb:bindings的node属性都会指向XSD中的单个节点,既解决了匹配过多的问题,也能成功将全大写类名/元素名转为驼峰式。
内容的提问来源于stack exchange,提问作者Abandooon
相关产品推荐
相关产品推荐

