2011-12-07 23 views
2

我想從XML文檔中提取所有知道英語的指南的名稱,問題是我不知道如何。我使用XQuisitor來查詢XML文檔。XQuery - 使用一個值訪問另一個值

段:

<GuideLang> 
<guideID>1</guideID> 
<lname>English</lname> 
</GuideLang> 
<GuideLang> 
<guideID>2</guideID> 
<lname>German</lname> 
</GuideLang> 
<GuideLang> 
<guideID>3</guideID> 
<lname>Swedish</lname> 
</GuideLang> 
<Guide> 
<guideID>1</guideID> 
<gname>John Smith</gname> 
</Guide> 
<Guide> 
<guideID>2</guideID> 
<gname>Weber Schneider</gname> 
</Guide> 

我知道:

element Result { 
//GuideLang[lname='English'] 
} 

給了我所有關於語言和引導的ID的信息 - 但我怎麼可以使用該ID僅打印指南的名字從Guide節點?

謝謝!

+0

「家庭作業」 - 標誌失蹤? –

+0

這只是我正在閱讀的一本書的「作業」,我認爲如果我知道這個問題的答案,那麼我將能夠弄清楚其餘的問題。 –

回答

2

你甚至不需要使用XQuery,XPath是精細,太:

//Guide[guideID=(//GuideLang[lname="English"]/guideID)]/gname 

這個查詢獲取其guideID等於guideID小號這是衆所周知的講英語和提取它們的gname一個所有指南。

確保瞭解XQuery的= - 操作員的集合語義!

+0

我正在做的任務需要使用XQuery;但是,我知道XQuery是XPath的擴展,這讓我懷疑XPath是否與這些簡單任務的XQuery是同義的 –

+1

@ michael-kaesy Any有效的XPath表達式,也是有效的XQuery .. – grtjn

+0

我如何獲得瞭解兩種語言的指南?我嘗試過:// guide [guideID =(// GuideLang [lname =「English」and「Swedish」/ guideID)]]/gname,但返回完全相同的答案。任何想法? –

4

使用此純的XPath 2.0表達式

/*/Guide 
    [for $gid in guideID 
    return ../GuideLang[guideID eq $gid and lname eq 'English'] 
    ] 
    /gname 

這假設所提供的文檔片段的節點是(未提供)的XML文檔的(未提供)頂元素的子元素。

這甚至可以被轉換成一個XPath 1.0表達式(注意沒有//使用!):

/*/Guide 
    [guideID 
    = 
    ../GuideLang[lname = 'English']/guideID 
    ] 
    /gname 

更新

只是對於那些奇怪爲什麼人民羣衆上面的第一個表達式是純XPath 2.0,這裏是一個完整的基於XSLT 2.0的驗證:

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

<xsl:template match="/*"> 
    <xsl:sequence select= 
    "/*/Guide 
      [for $gid in guideID 
      return ../GuideLang[guideID eq $gid and lname eq 'English'] 
      ] 
      /gname 
    "/> 
</xsl:template> 
</xsl:stylesheet> 

當該XSLT 2.0變換被應用在以下文獻(所提供的片段,包裝到一個頂部元件):

<t> 
    <GuideLang> 
     <guideID>1</guideID> 
     <lname>English</lname> 
    </GuideLang> 
    <GuideLang> 
     <guideID>2</guideID> 
     <lname>German</lname> 
    </GuideLang> 
    <GuideLang> 
     <guideID>3</guideID> 
     <lname>Swedish</lname> 
    </GuideLang> 
    <Guide> 
     <guideID>1</guideID> 
     <gname>John Smith</gname> 
    </Guide> 
    <Guide> 
     <guideID>2</guideID> 
     <gname>Weber Schneider</gname> 
    </Guide> 
</t> 

中的XPath 2.0表達式求值和正確地選擇的節點是輸出

<gname>John Smith</gname> 
+0

在純XPath中flwor? –

+0

@Ranon:這不是FLWR--這是(並且一直)是純XPath 2.0。在downvoting正確答案之前檢查您的XPath 2.0知識。 –

+0

對不起,你完全正確。即使檢查XPath 2.0語法,因爲我想知道。不知道我爲什麼能夠忽視「因爲」甚至在內容上,可悲的是對「for」的支持是無用的。 :(無論如何,出於性能方面的原因,我會堅持使用謂詞和隱式聯接,因爲它們傾向於獲得更好的優化 –

2

最直接的方式做到這一點,將是這樣的:

let $english-guide-ids := //GuideLang[lname = 'English']/guideID 
return 
    //Guide[guideID = $english-guide-ids] 

的「讓」語句是XPath 2.0 FLWOR語句的一個特定XQuery的擴展,但非常方便,保持代碼可讀。

有些人可能會爭辯說應該儘量限制//的使用。但是XQuery經常在XML數據庫中運行,並且他們通常能夠優化這種表達式。對於一個小小的任務,我不會擔心很多性能,雖然..

+0

編輯:我怎麼能只用這種方法返回指南的名稱? –

+0

@ michael-kaesy你說得對,上面的代碼會返回整個Guide元素,而不僅僅是gname的。只需在最後添加/ gname]來解決這個問題。請注意,將英文指南id放入一個變量中可以防止他們查找每個* Guide元素,與Ranon和Dimitre的解決方案一樣。 – grtjn