2012-03-28 53 views
0

使用XPath时,我继承了使用dom4j中和XPath来解析XML应用程序中使用的文字()函数:在dom4j的

的XML正在解析是类似以下内容:

<cache> 
    <content> 
    <transaction> 
     <page> 
     <widget name="PAGE_ID">WRK_REGISTRATION</widget> 
     <widget name="TRANS_DETAIL_ID">77145</widget> 
     <widget name="GRD_ERRORS" /> 
     </page> 
     <page> 
     <widget name="PAGE_ID">WRK_REGISTRATION</widget> 
     <widget name="TRANS_DETAIL_ID">77147</widget> 
     <widget name="GRD_ERRORS" /> 
     </page> 
     <page> 
     <widget name="PAGE_ID">WRK_PROCESSING</widget> 
     <widget name="TRANS_DETAIL_ID">77152</widget> 
     <widget name="GRD_ERRORS" /> 
     </page> 
    </transaction> 
    </content> 
</cache> 

单个节点正在使用以下方式进行搜索:

String xPathToGridErrorNode = "//cache/content/transaction/page/widget[@name='PAGE_ID'][text()='WRK_DNA_REGISTRATION']/../widget[@name='TRANS_DETAIL_ID'][text()='77147']/../widget[@name='GRD_ERRORS_TEMP']"; 

org.dom4j.Element root = null; 

SAXReader reader = new SAXReader(); 
Document document = reader.read(new BufferedInputStream(new ByteArrayInputStream(xmlToParse.getBytes()))); 
root = document.getRootElement(); 

Node gridNode = root.selectSingleNode(xPathToGridErrorNode); 

其中xmlToParse是一个类似于上面提供的摘录的xml字符串。

代码尝试使用xPath中提供的PAGE_ID和TRANS_DETAIL_ID获取页面的GRD_ERROR节点。

即使请求的节点位于正在搜索的xml中,我也会看到此selectSingleNode请求发生间歇(〜1-2%)故障(返回的节点为空)。

我知道有一些问题与在xPath中使用text()=相关,并且想知道是否有更好的方法来为这种搜索类型设置xPath字符串的格式。

+0

问题可能是由于树中存在碎片(相邻)文本节点。这不应该发生,但它确实:http://jira.codehaus.org/browse/JAXEN-67 – 2012-03-28 22:20:31

+0

是的。你可以像'follow-sibling ::'轴那样使用一些XPath魔术,或者某种选择多个节点并对它们进行处理,但是这个查询并不坏,应该可以工作,并且在不使用'text() 。我认为你最好的选择是更新到_dom4j v2.0.0 alpha 2_并希望问题会消失在那里。 – 2012-03-28 23:27:04

+0

感谢您的意见。我意识到与text()相邻的文本节点问题,因此我们搜索的节点中的文本没有空格。我们正在使用dom4j.1.6.1。此外,失败率大约为千分之一,但仍然每天导致2或3次失败。在发生故障时,我们打印正在分析的xml和用于日志的xPath。没有共同点 - 失败代表独特的xml和xPath组合。我会尝试使用新的dom4j v2.0.0。版本和报告我们的调查结果。 – jlawless 2012-04-11 20:30:51

回答

0

从您的片段看,有关于GRD_ERRORSGRD_ERRORS_TMPWRK_REGISTRATIONWRK_DNA_REGISTRATION有关的问题。

忽略的是,我会建议重写

//cache/content/transaction/page 
    /widget[@name='PAGE_ID'][text()='WRK_DNA_REGISTRATION'] 
    /../widget[@name='TRANS_DETAIL_ID'][text()='77147'] 
    /../widget[@name='GRD_ERRORS_TEMP'] 

//cache/content/transaction/page 
    [widget[@name='PAGE_ID'][text()='WRK_REGISTRATION']] 
    [widget[@name='TRANS_DETAIL_ID'][text()='77147']] 
    /widget[@name='GRD_ERRORS'] 

只是因为它使代码,在我的眼里,更易于阅读,并表示你似乎意味着什么更多很明显:“page元素有这些条件的孩子,然后拿这个小工具这个@name。”或者,如果这更接近你的想法,

//cache/content/transaction/page/widget[@name='GRD_ERRORS'] 
    [preceding-sibling::widget[@name='PAGE_ID'][text()='WRK_REGISTRATION']] 
    [preceding-sibling::widget[@name='TRANS_DETAIL_ID'][text()='77147']]