2013-05-22 90 views
0

我有以下XML:Xpath的搜索重複

<log> 
    <logentry revision="11956"> 
     <author>avijendran</author> 
     <date>2013-05-20T10:25:19.678089Z</date> 
     <msg> 
      JIRA-1263 - did something 
     </msg> 
    </logentry> 

    <logentry revision="11956"> 
     <author>avijendran</author> 
     <date>2013-05-20T10:25:19.678089Z</date> 
     <msg> 
      JIRA-1263 - did something 22 again 
     </msg> 
    </logentry> 
</log> 

我想忽略第一個後JIRA-1263的任何發生。

我想的XPath是(如果重複節點以下,如果你有重複其他地方(內心深處),則忽略哪些工作,但:

<xsl:variable name="uniqueList" select="//msg[not(normalize-space(substring-before(., '&#10;')) = normalize-space(substring-before(following::msg, '&#10;')))]" /> 
+1

實際上,消息文本節點以' JIRA-1263 - 做了某事'開始。我認爲你需要更詳細地說明你想要匹配什麼。您可能需要使用XPath的字符串操作例程來提取。 –

+0

我不認爲XPath 1.0的字符串操作功能就足夠了。 –

+0

感謝克里斯,基本上我想匹配的第一位 - JIRA-XXXX(E.g-JIRA-1263) – avijendr

回答

1

您可以在樣式表組通過他們的第一個字的日誌條目頂級定義關鍵

<xsl:key name="logentryByCode" match="logentry" 
    use="substring-before(normalize-space(msg), ' ')" /> 

現在,您需要選擇所有logentry元素,其中無論是

  • msg確實不是開始JIRA-nnnn(其中nnnn是一個數字)或
  • t他的條目第一個,其msg以該詞開始(即,的"JIRA-1234 - anything"第一次出現的每個票號)

(注意,這兩個條件不必是相互排斥的):

<xsl:variable name="uniqueList" select="log/logentry[ 
    (
    not(
     starts-with(normalize-space(msg), 'JIRA-') and 
     boolean(number(substring-before(substring(normalize-space(msg), 6), ' '))) 
    ) 
    ) 
    or 
    (
    generate-id() = generate-id(key('logentryByCode', 
      substring-before(normalize-space(msg), ' '))[1]) 
    ) 
]/msg" /> 

boolean(number(...))部分檢查的文本的字符串是否可被解析爲有效的非零數字(在這種情況下的文本是JIRA-後面的消息的第一個字的部分),generate-id技巧是稱爲Muenchian分組的一種特殊情況。

同樣,你可以組msg元素,而不是logentry元素,用在關鍵的定義match="msg"normalize-space(.)而不是normalize-space(msg)

+0

謝謝。通過對您的解決方案進行一些更改,我使其工作。 在關鍵部分,我不得不從**「logentry」**更改爲**「msg」**: ' avijendr

+0

@avijendr我已經用一個例子說明了我的答案,你可以如何獲得'msg'元素而不是'logentry'元素。 –

2

如果你想獲得每msg使用//msg[starts-with(normalize-space(.), 'JIRA-1263')]獲得輸出JIRA-1263 - did somethingJIRA-1263 - did something 22 again

如果你想獲得與同codition使用//*[starts-with(normalize-space(.), 'JIRA-1263')]這給相同的結果,以前的任何一個元素。

最後,如果你想獲得第一個msg在相同的條件下使用//logentry/msg[starts-with(normalize-space(.), 'JIRA-1263')][not(preceding::msg)]得到輸出JIRA-1263 - did something

+0

謝謝Navin/Ian在for-each中使用它。這些解決方案似乎不起作用。我基本上是爲了避免重複:「JIRA-1263 - 再次做了22件事」是「JIRA-1263 - 做了些什麼」的副本 – avijendr

+0

@avijendr你可以編輯這個問題,使它更清楚你實際上想要做什麼嗎?在您提供的輸入中您期望輸出什麼?如果有幾個不同的具有相同JIRA編號的日誌消息,你想要包括第一個,最後一個還是其他類型的生成的「摘要」(例如「JIRA-1263-2條目」)?這聽起來越來越像一個以JIRA號碼爲關鍵的標準Muenchian分組問題。 –

+0

嗨伊恩,我已經更新了這個問題。是的你是對的,我需要避免重複:我已經更新了對我有用的東西。 – avijendr

1

而這裏的另一種解釋是你試圖做什麼。
查找以JIRA-XXXX開頭的任何第一個logentry。
如果這是正確的嘗試:

log/logentry[ 
     starts-with(normalize-space(msg), 'JIRA-') and 
     not 
     (
     substring-before(normalize-space(msg), ' ')= substring-before(normalize-space(preceding::msg), ' ') 
    )] 

這將找到與JIRA-啓動,但還沒有前一個與你的榜樣第一空間(JIRA-XXXX)以前一樣串任何logentry。