2015-08-08 2 views
1

Мне нужно создать общий XPath, чтобы найти правильный узел, где критерием является дата и время. например найти узел для «03 мая», «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

Tricky! Это не очень эффективно, но является рабочий раствор (с 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 engine - в XMLStarlet, например, это будет --var date='"03 May"'; оценивая XPath в движке XQuery, он будет с 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"] /(. | следующий-sibling :: row [ нет (./ previous-sibling :: row [@Date! = ""] [1]/@ Date! = " 03 мая ») ] [not (./@ Date! =" "И ./@Date!= "03 мая")]) [@ Time = "12:17:44"] , но он говорит, что он не может скомпилировать. Я не вижу, что не так. Может быть, вы можете – AndrewSit

+0

Обновлен с помощью запроса, совместимого с XPath 1.0 (который является древним - 3.0 является текущим, но также используется ряд реализаций, в первую очередь libxml). –

+0

Еще раз спасибо. Я попробовал ваш новый Xpath 1.0 в freeformatter.com/xpath-tester.html» в /itemisationTable /строки [@ Date = "03 мая"] /следующая-родственного :: строка [ нет (./ предшествующего -sibling :: row [@Date! = ""] [1]/@ Date! = "03 мая") ] [not (./@ Date! = "" и ./@Date! = "03 мая")] [@ Time = "12:17:44"] |/itemisationTable/row [@ Date = "03 May"] [not (./@ Date! = "" и ./@Date! = "03 May"] [@ Time = "12:17:44"] Он по-прежнему отказывается компилировать. Так что ваш запрос слишком сложный для него или что-то еще не так – AndrewSit

Смежные вопросы