如何使用VTD从符合条件的School节点提取指定类型Branch节点?
VTD-XML 提取指定Branch节点的实现方案
需要从XML中筛选出ScId以RC开头的School节点,再从这些节点里提取Type为Residential的Branch节点并创建对应Branch对象。现有代码无法正确定位目标Branch节点,以下是修正后的实现方案。
原始XML数据
<?xml version="1.0" encoding="ISO-8859-1"?> <SchoolData> <School> <ScId>SC101-91</ScId> <Location> <Branch> <BranchId>Br-111</BranchId> <Type>Residential</Type> <RealType>Residential</RealType> </Branch> <Branch> <BranchId>BR-222</BranchId> <Type>Daycare</Type> <RealType>Daycare</RealType> </Branch> <Branch> <BranchId>Br-333</BranchId> <Type>Unknown</Type> <RealType>Unknown</RealType> </Branch> </Location> </School> <School> <ScId>RC101-92</ScId> <Location> <Branch> <BranchId>Br-111</BranchId> <Type>Residential</Type> <RealType>Residential</RealType> </Branch> <Branch> <BranchId>BR-222</BranchId> <Type>Daycare</Type> <RealType>Daycare</RealType> </Branch> <Branch> <BranchId>Br-333</BranchId> <Type>Unknown</Type> <RealType>Unknown</RealType> </Branch> </Location> </School> </SchoolData>
现有代码的问题
- 子XPath路径错误:多了冗余斜杠,且重复根路径的School筛选逻辑,未使用相对路径定位当前School节点下的Branch
- 未遍历找到的Branch节点,也没有提取节点内的字段值并赋值给Branch对象
修正后的完整实现代码
public static void main(String[] args) throws XPathParseExceptionHuge, XPathEvalExceptionHuge, NavExceptionHuge { String xmlPath = "config/school.xml"; // 初始化VTDGenHuge并解析XML文件 VTDGenHuge vg = new VTDGenHuge(); System.out.println("Parsing XML file..."); vg.parseFile(xmlPath, true, VTDGenHuge.MEM_MAPPED); VTDNavHuge vn = vg.getNav(); // 第一个AutoPilot:筛选ScId以RC开头的School节点 AutoPilotHuge schoolAp = new AutoPilotHuge(vn); schoolAp.selectXPath("/*/School[starts-with(ScId,'RC')]"); // 第二个AutoPilot:基于当前School节点,筛选Type为Residential的Branch(使用相对路径) AutoPilotHuge branchAp = new AutoPilotHuge(vn); branchAp.selectXPath("Location/Branch[Type='Residential']"); // 遍历所有符合条件的School节点 while (schoolAp.evalXPath() != -1) { System.out.println("Processing School with RC-prefixed ScId"); // 遍历当前School下的目标Branch节点 while (branchAp.evalXPath() != -1) { Branch branch = new Branch(); // 提取BranchId字段值 if (vn.toElement(VTDNavHuge.FIRST_CHILD, "BranchId")) { branch.setBranchId(vn.toNormalizedString(vn.getText())); vn.toElement(VTDNavHuge.PARENT); // 回到Branch父节点 } // 提取Type字段值 if (vn.toElement(VTDNavHuge.FIRST_CHILD, "Type")) { branch.setType(vn.toNormalizedString(vn.getText())); vn.toElement(VTDNavHuge.PARENT); // 回到Branch父节点 } // 提取RealType字段值 if (vn.toElement(VTDNavHuge.FIRST_CHILD, "RealType")) { branch.setRealType(vn.toNormalizedString(vn.getText())); vn.toElement(VTDNavHuge.PARENT); // 回到Branch父节点 } // 可在此添加Branch对象的后续处理逻辑(如存入集合) System.out.println("Created Branch: " + branch.getBranchId() + ", Type: " + branch.getType()); } // 重置Branch的AutoPilot,确保下一个School节点的遍历不受影响 branchAp.resetXPath(); } } // 假设的Branch实体类 class Branch { private String branchId; private String type; private String realType; // Getter和Setter方法 public String getBranchId() { return branchId; } public void setBranchId(String branchId) { this.branchId = branchId; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getRealType() { return realType; } public void setRealType(String realType) { this.realType = realType; } }
关键实现要点
- 相对路径XPath:
Location/Branch[Type='Residential']直接基于当前选中的School节点定位,避免全局重复查找 - 双AutoPilot分工:一个负责筛选目标School,另一个负责在当前School下筛选目标Branch,逻辑清晰高效
- 节点导航处理:使用
vn.toElement()在父子节点间切换,vn.toNormalizedString()处理文本中的空白字符 - AutoPilot重置:处理完一个School节点后,重置Branch的AutoPilot,保证下一轮遍历的正确性
内容的提问来源于stack exchange,提问作者technocrat
相关产品推荐
相关产品推荐

