使用VTD-XML的evalXPathToString()如何区分元素不存在与空元素?
解决VTD-XML中evalXPathToString无法区分元素不存在与空内容的问题
方案一:继承AutoPilot实现增强方法
通过继承AutoPilot类,添加状态标记和自定义方法,直接封装区分逻辑,完全匹配你期望的简洁调用方式:
import com.ximpleware.AutoPilot; import com.ximpleware.NavException; import com.ximpleware.XPathParseException; import com.ximpleware.VTDNav; public class EnhancedAutoPilot extends AutoPilot { private boolean elementNotFound; public EnhancedAutoPilot() { super(); } public EnhancedAutoPilot(VTDNav vn) { super(vn); } /** * 执行XPath:未找到元素返回null,找到但无内容返回空字符串,否则返回文本/属性值 */ public String evalXPathToStringOrNull() throws XPathParseException, NavException { elementNotFound = false; int nodeIndex = evalXPath(); // 未找到目标节点 if (nodeIndex == -1) { elementNotFound = true; return null; } VTDNav nav = getNav(); // 处理属性节点 if (nav.getTokenType(nodeIndex) == VTDNav.TOKEN_ATTR_NAME) { return nav.getString(nodeIndex); } // 处理元素节点,获取文本内容 int textIndex = nav.getText(nodeIndex); return textIndex == -1 ? "" : nav.getString(textIndex); } /** * 重载方法:直接传入XPath执行 */ public String evalXPathToStringOrNull(String xpath) throws XPathParseException, NavException { selectXPath(xpath); return evalXPathToStringOrNull(); } /** * 判断上一次XPath是否未找到元素 */ public boolean wasNotFound() { return elementNotFound; } }
使用示例
// 初始化VTDNav和增强版AutoPilot VTDNav nav = new VTDGen().parseFile("test.xml", false); EnhancedAutoPilot ap = new EnhancedAutoPilot(nav); // 方式1:直接获取结果 String emptyElementResult = ap.evalXPathToStringOrNull("/root/emptyElement"); // emptyElementResult为空字符串(元素存在但无内容) String nonExistentResult = ap.evalXPathToStringOrNull("/root/nonExistentElement"); // nonExistentResult为null(元素不存在) // 方式2:先执行再判断 ap.selectXPath("/root/targetElement"); String result = ap.evalXPathToString(); if (ap.wasNotFound()) { result = null; }
方案二:编写静态工具类(无需继承)
如果不想修改AutoPilot的继承结构,可编写工具类封装逻辑,灵活性更强:
import com.ximpleware.AutoPilot; import com.ximpleware.NavException; import com.ximpleware.XPathParseException; import com.ximpleware.VTDNav; public class VTDXmlUtils { /** * 执行AutoPilot当前的XPath,返回null(未找到)/空字符串(无内容)/实际值 */ public static String evalXPathToStringOrNull(AutoPilot ap) throws XPathParseException, NavException { int nodeIndex = ap.evalXPath(); if (nodeIndex == -1) { return null; } VTDNav nav = ap.getNav(); // 处理属性节点 if (nav.getTokenType(nodeIndex) == VTDNav.TOKEN_ATTR_NAME) { return nav.getString(nodeIndex); } // 处理元素或文本节点 int textIndex = nav.getText(nodeIndex); return textIndex == -1 ? "" : nav.getString(textIndex); } /** * 重载方法:直接传入XPath执行 */ public static String evalXPathToStringOrNull(AutoPilot ap, String xpath) throws XPathParseException, NavException { ap.selectXPath(xpath); return evalXPathToStringOrNull(ap); } }
使用示例
VTDNav nav = new VTDGen().parseFile("test.xml", false); AutoPilot ap = new AutoPilot(nav); String result = VTDXmlUtils.evalXPathToStringOrNull(ap, "/root/target"); // result为null(元素不存在)/""(元素存在无内容)/实际文本
关键逻辑说明
两种方案都通过以下核心逻辑区分场景:
- 调用
evalXPath()返回-1:判定为元素/属性不存在,返回null - 找到节点后:
- 若为属性节点,直接返回属性值(空值则返回空字符串)
- 若为元素节点,调用
getText()判断是否有文本内容:返回-1则元素存在但无内容,返回空字符串;否则返回实际文本
该逻辑兼容元素、属性、文本节点等多种XPath场景,同时保持调用的简洁性。
内容的提问来源于stack exchange,提问作者S Bullen
相关产品推荐
相关产品推荐

