2015-08-08 193 views
1

我需要构建一个通用的XPath来查找正确的节点,其中的标准是日期和时间。例如找到节点“5月3日”,“12:17:44”Xpath,找到两个其他节点之间的节点

XML具有日期和时间标记。 不方便的是,日期标记仅填充为当天的第一个事件。 (时间标记总是被填充)

我已经试过这样:

/itemisationTable/row[@Date="03 May"]/following-sibling::row[@Time="12:17:44"] 

它工作正常,但它是不正确的,因为这

/itemisationTable/row[@Date="03 May"]/following-sibling::row[@Time="21:12:06"] 

还发现一个结果,它不应该。


我的另一个问题是,

/itemisationTable/row[@Date="03 May"]/following-sibling::row[@Time="09:34:13"] 

应该找到一个节点,但事实并非如此。


如果有人可以帮助我使用XPath,因为它超出了我的Xpath技能,所以我会很感激。

这里是XML

<itemisationTable index="1" name="Belgium - SMS/Data" total="1.522"> 
<row Date="03 May" Time="09:34:13" Number="xphone.com" Description="Roaming Data" Origin="Belgium" Destination="Other Provider" InBundle="" Taxable="T" Duration="12.57 MB" Cost_exc_VAT="1.258" /> 
<row Date="" Time="10:43:41" Number="4428" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="10:43:44" Number="4428" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="12:17:44" Number="4408" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="21:10:50" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="21:11:55" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="04 May" Time="21:12:06" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="21:22:34" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="21:23:23" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="21:23:31" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="05 May" Time="21:23:56" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="21:30:45" Number="4412" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="22:24:35" Number="4431" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="" Time="22:24:38" Number="4431" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
<row Date="06 May" Time="" Number="xphone.com" Description="Roaming Data" Origin="Belgium" Destination="Other Provider" InBundle="" Taxable="T" Duration="2.59 MB" Cost_exc_VAT="0.264" /> 
<row Date="" Time="07:09:15" Number="4483" Description="xphone SMS" Origin="Belgium" Destination="UK" InBundle="B" Taxable="" Duration="1" Cost_exc_VAT="0.000" /> 
</itemisationTable> 

回答

2

整蛊的一个片段!这不是特别有效,但它工作解决方案(使用XPath 2.0):

/itemisationTable 
    /row[@Date=$date] 
    /(self::row | following-sibling::row[ 
    not(./preceding-sibling::row[@Date != ""][1]/@Date != $date) 
    ][not(./@Date != "" and ./@Date != $date)])[@Time=$time] 

在XPath 1.0,这得到多毛:

/itemisationTable 
    /row[@Date=$date] 
    /following-sibling::row[ 
    not(./preceding-sibling::row[@Date != ""][1]/@Date != $date) 
    ][not(./@Date != "" and ./@Date != $date)][@Time=$time] 
| /itemisationTable/row[@Date=$date][not(./@Date != "" and ./@Date !=$date][@Time=$time] 

设置$date$time通过你的XPath引擎 - 在XMLStarlet中,例如,这将是--var date='"03 May"';在XQuery引擎中评估XPath将与declare variable $date="03 May";等等。

重要的是使用preceding-sibling回溯并查看您是否越过边界,排除任何真的节点。

对于具有足够表现力的语言来构建高效的解决方案,我想切换到XQuery。


要允许复制/粘贴测试,下面已经成功地使用在http://www.freeformatter.com/xpath-tester.html

/itemisationTable /row[@Date="03 May"] /following-sibling::row[  not(./preceding-sibling::row[@Date != ""][1]/@Date != "03 May") ][not(./@Date != "" and ./@Date != "03 May")][@Time="21:11:55"] | /itemisationTable/row[@Date="03 May"][not(./@Date != "" and ./@Date != "03 May")][@Time="21:11:55"] 
+0

谢谢您的帮助迄今为止。我实际上没有使用引擎,只准备另一个系统的Xpaths并使用http://www.freeformatter.com/xpath-tester.html测试它们。 我在测试仪中试过这个, /itemisationTable /row。[@ Date =“03 May”] /(。| following-sibling :: row [0]/[before-sibling :: row [@Date!=“”] [1]/@ Date!=“ 03月5日“) ] [不是(./@日期!=”“和./@Date!=“03 May”)])[@ Time =“12:17:44”] 但它说它无法编译。 我看不出有什么问题。也许你可以 – AndrewSit

+0

更新与XPath 1.0兼容的查询(这是古老的 - 3.0是最新的 - 但也是一些实现,最着名的是libxml使用)。 –

+0

再次感谢您。我已经在freeformatter.com/xpath-tester.html' as /itemisationTable /row [@ Date =“03 May”] /following-sibling :: row [ not(./)前面尝试了新的Xpath 1.0 -tyle :: row [@Date!=“”] [1]/@ Date!=“03 May”) ] [not(./@ Date!=“”and ./@Date!=“May May” )] [@ Time =“12:17:44”] |/itemisationTable/row [@ Date =“03 May”] [not(./@ Date!=“”and ./@Date!=“May May”] [@ Time =“12:17:44”] 它仍然拒绝编译,所以要么你的查询太复杂了,要么其他的错误 – AndrewSit

相关问题