[英]XPath 1 query
我發布了類似的問題,並且得到了非常有用的答復。 現在,問題有所不同,因此我將其發布。 我指定它是與XPath 1相關的問題。 這是我的XML文件的內容:
<?xml version="1.0" encoding="ISO-8859-1"?>
<mainNode>
<subNode>
<h hm="08:45">
<store id="1563">Open</store>
</h>
<h hm="13:00">
<store id="1045">Open</store>
<store id="763">Open</store>
<store id="1047">Open</store>
</h>
<h hm="16:30">
<store id="1045">Open</store>
<store id="763">Open</store>
<store id="1047">Open</store>
</h>
<h hm="20:00">
<store id="1045">Open</store>
<store id="1043">Open</store>
<store id="1052">Open</store>
</h>
<h hm="22:00">
<store id="763">Open</store>
<store id="1052">Open</store>
</h>
</subNode>
</mainNode>
我的程序獲取當前時間:如果我是12.40,則必須檢索下一個h hm(13.00)的所有商店ID:此問題已解決。
檢索數據后,通過第二個XPath查詢,我必須知道直到當天(以XML文件表示)當天打開一個商店。 因此,假設商店是標識為ID = 1045的商店,現在是上午12.40。 該存儲將在20.00關閉,因為在h hm = 13.00子節點,h hm = 16.30子節點和h hm = 20.00子節點中可以找到它。 因此,我必須得到20.00。
情況2:現在是12.40,我必須知道763何時關閉。 無論它是否包含在最后一個節點中(h hm = 22.00),它將在16.30關閉。 因此,我必須得到16.30。
這可能嗎?
提前致謝。
這是如何構造XPatch表達式的方法:
以下XPath表達式選擇所需的結果
($vOpen[not(count(following-sibling::h[1] | $vOpen)
=
count($vOpen))
][1]/@hm
|
$vOpen[last()]/@hm
)
[1]
其中$vOpen
定義為:
$vge1240[store/@id=$vId]
$vge1240
定義為:
/*/*/h[translate(@hm,':','') >= 1240]
$vId
定義為:
1045
要么
763
上面的變量可以在XSLT樣式表中定義和引用,或者,如果XPath嵌入在另一個主機中,則每個變量引用都必須用變量定義的右側替換。 在這種情況下,完整的XPath表達式將是:
(/*/*/h[translate(@hm,':','') >= 1240][store/@id=763]
[not(count(following-sibling::h[1]
|
/*/*/h[translate(@hm,':','') >= 1240][store/@id=763]
)
=
count(/*/*/h[translate(@hm,':','') >= 1240][store/@id=763]))
]
[1]
/@hm
|
/*/*/h[translate(@hm,':','') >= 1240][store/@id=763]
[last()]
/@hm
)
[1]
說明 :
($vOpen[not(count(following-sibling::h[1] | $vOpen)
=
count($vOpen))
][1]/@hm
|
$vOpen[last()]/@hm
)
[1]
表示以下內容:
在“開放”小時內包含ID(763)的所有條目中
采取那些緊隨其后的兄弟姐妹不屬於該集合的對象(封閉或不包含763)
從那些拿第一個。
從上面在步驟3中選擇的節點中獲取第一個(按文檔順序),並從$vOpen
最后一個元素。 如果其中所有條目都包含給定的ID,則它將選擇“開放”小時中的最后一個條目。
在這里,我們本質上使用Kayesian方法處理兩個節點集 $ ns1和$ ns2的交集 :
$ ns1 [count(。| $ ns2)= count($ ns2)]
在您提到的最后一個問題中,我將重復我對您的回答的最后一部分。
將XML加載到更符合您的需求的某些數據結構中將更為實用。 第二個問題只是加強了該建議的明智性。
如果您要查找的商店ID在$store
,則將獲取包含該ID的最后一個h/@hm
,后跟一個不包含該ID的h
或包含該商店的最后h/@hm
ID(用於最后關閉h/@hm
商店)。
//h[not(store/@id=$store)]/preceding-sibling::h[store/@id = $store][1]/@hm | //h[store/@id=$store][last()]/@hm
要使用示例XML在XSLT中進行測試,請執行以下操作:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:variable name="store" select="763"/>
<xsl:template match="/">
<closes>
<xsl:value-of select="//h[not(store/@id=$store)]/preceding-sibling::h[store/@id = $store][1]/@hm | //h[store/@id=$store][last()]/@hm"/>
</closes>
</xsl:template>
</xsl:stylesheet>
打印<closes>16:30</closes>
。 如果將$store
更改$store
1052,它將打印<closes>22:00</closes>
。
我認為這可行。 它會找到store / @ id的最后一個連續出現的時間(在開始時間之后),其中@id = $ id,這是我相信您正在尋找的內容。
<xsl:variable name="id" select="'1045'"/>
<xsl:variable name="st" select="translate('12:40',':','')"/>
...
((//h[translate(@hm,':','') >= $st])[position() = count(preceding-sibling::*[store/@id=$id])+1 and store/@id=$id])[last()]/@hm
說明:首先,選擇與提供的開始共享開始時間> =的所有元素。 然后,在這些結果中,選擇最后一個元素的@hm屬性,該屬性的位置等於其中包含請求的store / @ id標簽的先前元素的數量。
這個簡短版本的一個限制是,如果商店ID在開始時間之后的第一個元素內沒有出現,它將失敗。 下面的代碼通過從包含正確的store / @ id的開始時間之后的第一個開始修復了該限制,但是有點麻煩:
<xsl:variable name="id" select="'1045'"/>
<xsl:variable name="st" select="translate('12:40',':','')"/>
...
((//h[translate(@hm,':','') >= $st and position() >= count(//h[not(preceding-sibling::*[store/@id=$id])])])[position() = count(preceding-sibling::*[store/@id=$id])+1 and store/@id=$id])[last()]/@hm
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.