2011-10-27 58 views
2

我正在嘗試計算與查詢匹配的每個元素的特定屬性(例如@root)的每個值的出現次數。其中一些匹配元素沒有屬性,但我也想要統計這些屬性(即也列出了沒有屬性的匹配元素的數量)。如果屬性不存在,如何選擇屬性或回退值?

目前我使用這個,但這不匹配不具有root屬性的節點。計數由應用程序完成,這使我能夠顯示中間結果。

//node[@rel='su']/@root 

我想是這樣

//node[@rel='su']/string(if .[@root] then @root else 'fallback-value') 

的查詢運行的Berkeley DB,XML等等XPath2和XQuery還可能用於解決此問題。爲了澄清,我正在尋找一個將@root屬性不存在作爲特殊情況的查詢;即就好像該屬性確實存在並具有'fallback-value'作爲值。

回答

1

試試這個:

//node[@rel='su']/(@root/string(), 'no-value')[1] 

沿用了原先的答案被誤解的問題

你爲什麼不只是使用

//node[@rel='su'] 

呢?它將匹配具有@root屬性的node元素,以及那些不具有@root屬性的元素。

鑑於node最多隻能有一個@root屬性,因此對節點進行計數就足夠了。

+0

它是一個應用程序,顯示@root以及如何他們經常發生每所有發現的價值,這就是爲什麼我需要查詢值。 – Jelmervdl

+0

我更新了我的答案;我最初誤解了你的問題。 – gioele

+0

但是,如何明確地要求「如何計算每個值的出現」? – Gunther

0

這是怎麼回事?

//node[@rel='su' and not(@root)] 

這應該與沒有root屬性的節點匹配。

1

這可以很容易地使用XQuery來完成。首先,收集的匹配值,同時執行備用廣告政策:

let $matches := //node[@rel='su']/(data(@root), '')[1] 

以上是在你的問題所示的表達式的一個略低校正措詞。但是請注意,它將使用零長度值處理根屬性,這與不存在的根屬性相同。

然後,通過不同的值組,並且計數出現的每個組的數目:

for $value in distinct-values($matches) 
    let $count := count($matches[. = $value]) 
    return <value count="{$count}">{$value}</value> 

當施加到該輸入,

<x> 
    <node rel="su" root="A"/> 
    <node rel="su" root="A"/> 
    <node rel="su" root="B"/> 
    <node rel="su" root=""/> 
    <node rel="su"/> 
    <node rel="su"/> 
    </x> 

結果可能是

<value count="2">A</value> 
    <value count="1">B</value> 
    <value count="3"/> 

要強制執行結果的特定順序,請添加order by子句:

for $value in distinct-values($matches) 
    let $count := count($matches[. = $value]) 
    order by $value 
    return <value count="{$count}">{$value}</value> 
+0

我非常喜歡這個解決方案。目前,計數是在應用程序本身完成的,這允許我向用戶顯示中間結果,這是我真正想要維護的功能。如果沒有必要,這將是整個問題的最佳解決方案。 – Jelmervdl

0

使用

concat('Having @root: ', count(//node[@rel='su']/@root), 
     ', Not having @root: ', count(//node[@rel='su'][not(@root)]), 
     ', Having @root occur ', 
     floor(count(//node[@rel='su']/@root) div count(//node[@rel='su']) * 100), 
     '% of the time.' 
     ) 

XSLT - 基於驗證

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:value-of select= 
    "concat('Having @root: ', count(//node[@rel='su']/@root), 
      ', Not having @root: ', count(//node[@rel='su'][not(@root)]), 
      ', Having @root occur ', 
      floor(count(//node[@rel='su']/@root) div count(//node[@rel='su']) * 100), 
      '% of the time.' 
     ) 
    "/> 
</xsl:template> 
</xsl:stylesheet> 

當下面的XML文檔應用這種轉變:

<t> 
<node rel="su" root="2"/> 
<node rel="su" root="1"/> 
<node rel="su" /> 
<node rel="su" root="4"/> 
<node rel="su" root="5"/> 
<node rel="su" /> 
<node rel="su" root="7"/> 
<node rel="su" root="8"/> 
<node rel="su" /> 
<node rel="su" /> 
</t> 

想要的,正確的結果產生

Having @root: 6, Not having @root: 4, Having @root occur 60% of the time. 
+0

我並不是在尋找@root屬性本身的統計信息,而是根據它的值找到它。我想將屬性的不存在作爲一個特殊的值來對待,所以我可以用與計算所有找到的值相同的方式來計算它發生的頻率。 – Jelmervdl

+0

@Jelmervdl:如果是這樣,你必須接受Gunther的答案。此外,你需要明顯改善你的問題定義,而不是讓人猜測和浪費他們的時間。 –

相關問題