<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Vincent.Chan‘s Blog

    常用鏈接

    統計

    積分與排名

    網站

    最新評論

    實用數據綁定: 使用 XPath 作為數據綁定工具,第 1 部分:使用 XPath 選擇 XML 文檔部分

    級別: 中級

    Brett McLaughlin, 作家,編輯, O'Reilly Media, Inc.

    2005 年 12 月 22 日

    通 常人們不把 XPath 看作是一種數據綁定 API。除了作為其他規范的一部分以外,XPath 甚至還沒有引起 XML 世界的過多關注。但是只要真正理解了 XPath 是什么以及如何使用它,特別是在 Java? 編程環境中,它就會成為一種強大的數據綁定工具,常常優于傳統的數據綁定 API 如 JAXB 或 JaxMe。Brett McLaughlin 的 “實用數據綁定” 專欄首先用兩期文章探討了作為數據綁定工具的 XPath。

    到目前為止,本專欄一直專注于數據綁定的傳統定義和用法:將 XML 文檔轉換成 Java 表示并用于通常的 Java 方法中(比如 getName()setAddress())。 然后將 Java 對象再轉換成 XML 表示,通常序列化(保存)到磁盤。我還討論過另一種方向的轉換,即把 Java 對象轉換成 XML, 然后使用轉換的 XML(可以通過網絡連接發送出去,或者作為應用程序中另一個消費 XML 的組件的輸入)。這都是非常有效和實用的數據綁定的用例,但是還沒有包括所有的可能性。本文和下一期文章將介紹另一種方法,即使用 XPath 技術進行數據綁定。

    如果您使用數據綁定很長時間了,通常會提供一個約束集(比如 XML 模式或 DTD),用 API 生成表示該約束集的類。然后使用這些類加載 XML 數據,將其中的數據序列化為 XML。這是一種完善的解決方案,但是并非惟一的不使用 SAX 或 DOM 等底層 API 從 XML 文檔中讀取數據的方法。XPath,您可能聽說過這種規范,就是另一種方法。即使您沒有 聽說過 XPath,也可能在某些時候已經用到過它。通過本文,您將了解 XPath 是什么,知道如何使用它,看看它為什么像一種數據綁定 API,甚至可以漂亮地完成其他數據綁定任務很難實現的工作。

    總是為他人作嫁衣……

    XPath 是最常用而不為人知的 XML 技術之一。它實際上是 常用的 XML 技術 —— XML 轉換必不可少的組成部分。在將來的 Web 中它也起著重要的作用,因為它對 XLink 和(特別是) XPointer 至關重要。甚至 XForms 也暗中要用到它。

    那么人們為什么不把 XPath 看作一種獨立的技術呢?很大程度上是因為其他語言中獨立處理 XPath 的 API 還剛剛出現。但是如果使用過 XSLT 或 XPointer,或者處理過更先進的 XML Schema,那么您可能已經走到前面了。

    XPath 在 XSLT 中的作用

    如果使用過 XSLT,幾乎可以肯定曾經看到過 XPath 而且至少在一定程度上看著面熟,即使您并沒有意識到。看一看 清單 1,這是一個非常簡單的 XSL 樣式表的一部分。


    清單 1. XSL 樣式表中的 XPath
    												
    														

    <xsl:template match="address">
    <h1>Addresses</h1>
    <hr />
    <table>
    <tr><th>Street</th><th>City</th><th>State</th><th>Zip Code</th></tr>
    <xsl:apply-templates select="address" />
    </table>
    </xsl:template>
    <xsl:template match="address" />
    <tr>
    <td><xsl:value-of select="street" /></td>
    <td><xsl:value-of select="city" /></td>
    <td><xsl:value-of select="state" /></td>
    <td><xsl:value-of select="zipCode" /></td>
    </tr>
    </xsl:template>

    比方說,當您看到 select="address" 或者 select="zipCode" 的時候,您看到的就是應用中的 XPath。包圍在引號中的文本就是 XPath 表達式,盡管非常簡單,要讓樣式表工作卻是不可或缺的。

    實際上,即使編寫最簡單的 XML 轉換,如果樣式表中沒有 select 會怎么樣?根本不可能!這是因為 XPath 是 XML 轉換從而也是 XSLT 的完整的一部分。如果您認為自己是一位 XSL 專家,您可能比自己認為的更熟悉 XPath。

    XPointer 中的 XPath

    XPointer 是另一種大量使用 XPath 的 API,盡管不像 XSL 那么常用,但是也逐漸展露頭角。清單 2 展示了一篇文檔中指向另一篇文檔的鏈接。


    清單 2. XPointer 上下文中 XPath 的用法
    												
    														

    <link xmlns:xlink="http://www.w3.org/2000/xlink"
    xlink:type="simple"
    xlink:href="cd.xml#xpointer(
    /cds/cd[@title='August and Everything After'])">

    要考慮的一些問題

    注意指向 XML 文檔的一部分的 XPath 代碼例子。XPath 表達式沒有涉及到元素或屬性,而是直接包含對這些 XML 結構名稱的引用。這應該讓您想起數據綁定。

    這是一段稍微復雜的 XPath。它選擇了根元素 cds 中的 cd 元素,該元素有一個 title 屬性等于 August and Everything After,這些內容都在 cd.xml 文檔中。討論這些似乎有點為時過早,但是先不要擔心語法。關鍵是要看到 XPointer 和 XSL 一樣大量使用了 XPath,事實上沒有它 XPointer 就無法存在。再說一次,XPath 是用于選擇數據的重要組件。

    在 XForms 中使用 XPath

    XForms 是一種相對較新的 XML 技術,比不上 XSL 普及,甚至還比不上 XPointer 或 XLink。但是仍然值得提一下,因為它在 input 元素的 ref 屬性中使用 XPath 表達式。可以設置一個 input 并將其綁定到 XML 文檔中的特定元素(或屬性),如 清單 3 所示。


    清單 3. XForms 組件使用 XPath 引用綁定到表單的 XML 文檔
    												
    														

    <input ref="xhtml:html/body/xhtml:p[@id='greentea']/
    xhtml:description" />

    清單 3 中的 XForms 語句將輸入控件綁定到 XHTML 文檔的特定元素。在這里 XPath 同樣是指定具體元素的關鍵。后面將提到它允許使用一些非常高級的選擇條件。

    在很大程度上 XForms 是一種尚未得到支持的技術,但是當使用 XForms 的時候,現在學習的 XPath 是一種很好的工具。將這些關于 XSL、XLink 和 XInclude 的知識結合起來就夠了!





    回頁首


    選擇內容:基礎

    現在您已經確信 XPath 非常有用而且無處不在了,下面開始學習語法吧。如果剛接觸 XPath,本課程將幫助您開始學習和領會 XPath 的結構。如果是一位 XSL 或 XLink 和 XPointer 老手,也可了解為什么 要構造那些奇怪的路徑。您可能已經知道獲取感興趣的數據的其他方法,也許是更好的方法。

    首先要認識到稱 XPath 為一種語言有點過于鄭重其事。它實際上是選擇和處理 XML 文檔中的內容的一種語法。即使在 XPath 中使用的函數和運算符也都與選擇有關。在 XPath 中不會創建變量,比方說不可能運行 一個 XPath 程序。沒有這些東西。如果您開始認識到 XPath 是一種巧妙的、有益的選擇 XML 元素和屬性的方法,然后使用選擇的值,您就已經領先于大多數 XML 開發人員了。XPath 不是要對 XML 什么事情,而是要 XML 中取得一些內容。

    選擇元素

    設置上下文

    設置上下文不是 XPath 的工作。事實上,根本不能 用 XPath 設置上下文。相反,要用其他使用 XPath 在文檔中導航的 API 來設置上下文。比如,XSLT 根據應用的模板設置上下文,XForms(一般來說)每次都從根上下文開始。因此理解上下文更多的是需要了解使用 XPath 的 API,而不是 XPath 本身。

    對于 XPath 來說第一步是找到一個引用元素的句柄??墒窃谶x擇元素之前需要理解當前上下文。上下文就是在 XML 文檔中的位置。比方說,您可能在根元素上,那根元素就是上下文。當然也可能在第一個 person 元素的第二個 address 元素上。在開始移動和選擇內容之前,需要知道上下文。

    只要理解了上下文,就可以掌握 XPath 語法了。以 清單 4 中的 XHTML 文檔為例。


    清單 4. Head First Lounge 的 XHTML
    												
    														

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html;
    charset=ISO-8859-1" />
    <title>Head First Lounge Elixirs</title>
    <link type="text/css" rel="stylesheet" href="../lounge.css" />
    </head>
    <body>
    <h1>Our Elixirs</h1>
    <h2>Green Tea Cooler</h2>
    <p class="greentea">
    <img src="../images/green.jpg" alt="Green Tea Cooler" />
    Chock full of vitamins and minerals, this elixir
    combines the healthful benefits of green tea with
    a twist of chamomile blossoms and ginger root.
    </p>
    <h2>Raspberry Ice Concentration</h2>
    <p class="raspberry">
    <img src="../images/lightblue.jpg"
    alt="Raspberry Ice Concentration" />
    Combining raspberry juice with lemon grass,
    citrus peel and rosehips, this icy drink
    will make your mind feel clear and crisp.
    </p>

    <h2>Blueberry Bliss Elixir</h2>
    <p class="blueberry">
    <img src="../images/blue.jpg" alt="Blueberry Bliss Elixir" />
    Blueberries and cherry essence mixed into a base
    of elderflower herb tea will put you in a relaxed
    state of bliss in no time.
    </p>
    <h2>Cranberry Antioxidant Blast</h2>
    <p>
    <img src="../images/red.jpg" alt="Cranberry Antioxidant Blast" />
    Wake up to the flavors of cranberry and hibiscus
    in this vitamin C rich elixir.
    </p>
    <p>
    <a href="../lounge.html">Back to the Lounge</a>
    </p>
    </body>
    </html>

    如果在 清單 4 中的上下文是 html 元素,就可以直接使用名稱選擇一個子元素。比如選擇 body 元素可使用 XPath 表達式 body。如果想訪問嵌套在 body 中的 h1 元素則使用 body/h1。如果認為這有點類似于目錄路徑,那么就對了。選擇元素使用 元素名/子元素名 這樣的形式。

    不過在前進之前要認識到 XPath 表達式可能返回多個 元素。結果元素集稱為節點集。(事實上,用 XPath 選擇的所有實體 —— 元素、屬性和值 —— 都稱為節點。)比如下面的路徑:

    												body/p
    										

    清單 4body 有五個不同的 p 子元素,因此那個表達式返回包含五個節點的節點集(正如您所期望的, 只是第一個 p 元素)。注意,有時候您得到了預期的結果,但是很可能比您打算 要求的多。

    還有更多需要注意的地方?,F在給出的表達式僅僅返回實際的元素??赡苓€要獲得這些節點的值。如果需要元素的值(假設元素包含文本數據),需要使用 text() 函數。要獲得第一個 h1 的文本,應使用 body/h1/text(),對于清單 4 將返回 Our Elixirs。

    選擇屬性

    當然可以選擇的不僅僅是元素。前面已經提到還可以選擇屬性。選擇屬性的時候要在屬性名前使用 @ 符號,其他方面和元素都一樣。

    再回到 清單 4 這個例子,可以使用 head/meta/@http-equiv 返回 meta 元素 http-equiv 屬性的值。類似地,head/link/@type 返回 link 元素的 type 屬性。

    必須知道,選擇屬性的時候您得到的是它的值,而不像元素那樣返回節點。因此對于屬性選擇器,返回值(雖然不確切但是很有用)是一個值,對于一個元素則是一個節點集(包含一個節點)。

    在文檔中移動

    目前為止看到的都是理想的情況,特別是使用文檔的根作為上下文比較簡單。但是顯然情況并非總是如此。這正是目錄結構的真正有用的地方。要從當前上下文移動到上一級,只要使用 .. 運算符。比方說,假設上下文是 body 元素,現在需要獲得網頁的標題(包含在文檔 head 下的 title 元素中),可以使用 ../head/title/text()。如果您開始感覺到就像是改變 UNIX 或 Mac OS X 終端上的目錄,這就對了!

    如果上下文是 body 中第二個 pimg 元素,要得到標題該怎么辦呢?可以使用 ../../../head/title/text()。但是數這些 ../ 很快就變得單調乏味了。因此能直接跳到根元素就好了,再想一想 UNIX,使用 / 返回到根元素就毫不奇怪了。同樣的選擇器更簡單的形式為 /html/head/title/text()。雖然沒有縮短,但是更清楚了。有了 ..// 之后,基本上就能移動到需要的任何地方了。

    多重選擇

    考慮到使用一個 XPath 表達式可以選擇多個節點,事情就更有趣了。您可以使用對應多個節點的簡單表達式,比如 /html/body/h2 來進行多重選擇。但是也可使用通配符 進一步精化這些選擇。XPath 中有三個統配符:

    • * 與任何元素匹配,無論元素名是什么
    • node() 與所有的節點類型匹配(元素、文本節點、注釋、屬性,等等)
    • @* 與所有的屬性節點匹配,無論屬性名是什么

    比如,可以使用 /html/body/* 選擇 body 元素的所有直接子元素。也可用 /html/head/meta/@* 選擇 meta 標記的所有屬性。

    所有這些情況下,要記住您得到的是一個節點集,因此不應該滿足于處理某個值就結束(除非您已經選擇了一個屬性,稍后要講到)。但是,只要使用方法、函數或模板處理多個節點,這些技術就很重要。





    回頁首


    更有趣的東西

    基本的東西很好,但有時候還需要點特別的讓您身邊的同事眼花繚亂的東西,或者需要一點特殊的 功能。這種情況下這些基礎可能就不夠了。雖然很難巨細無遺地介紹 XPath,但下面給出一些高級技巧,可以幫助您在 XPath 應用程序中取得需要的節點(或節點集)。

    更大的一般性

    到目前為止,看到的路徑都是選擇一個節點,并假設您知道該節點在何處。比方說,您知道 title、imgp 在文檔中什么位置,只需要導航到這些元素。但有時候可能希望打破這些結構,僅僅擷取某種元素而不管其位置(或者無論給定的起始上下文的位置)。為此可使用后代選擇器。

    后代選擇器用雙斜線 // 表示。使用它告訴 XPath 選擇所有指定的節點,無論嵌套得多深。比如這個簡單的特定于 XHTML 的 XPath:

    												/html/body//table
    										

    XPath 選擇嵌套在 XHTML 的 body 元素中的所有table 元素,不論直接嵌套在 body 中(如 /html/body/table),還是嵌套了多層(如 /html/body/table/tr/td/table)。這種情況下,嵌套的 table 和頂層 table 同時被選中。

    不是很合 XML 的風格

    在標準 XML 術語中,屬性不屬于 元素,而是與元素關聯,有時候也說在元素上。但是,XPath 不能處理元素及其屬性之間的關系。因此只能盡自己最大的努力:將屬性看作是屬于它們所在的元素。因此選擇 pclass 屬性要使用 p/@class。要訪問屬性所在的元素,可使用 @class/..。實際上是從屬性上移 一層而選擇元素。從技術上說這不是很好的 XML,但卻是完全正確的 XPath。

    當與屬性結合使用的時候就變得很有趣了(使用 @)。比方說,假設要選擇具有 id 屬性的所有元素??墒褂?//@id,首先跳回根元素然后選擇文檔中的所有 id 屬性。但是實際上要訪問的是元素而不是屬性,因此需要從屬性上移一層到包含這些屬性的元素:

    												//@id/..
    										

    您應該嘗試結合這些不同的方法,會看到一些很有意思的結果。

    匹配條件

    假設有一個條件希望作為匹配的基礎,比如需要 class 屬性值為 greenteap 元素。如果知道如何使用方括號,這一點在 XPath 中很容易做到。下面是一個例子:

    												
    														
    /html/body/p[class="greentea"]

    方括號用于指定條件,可使用 = 甚至 <>。也許要用一個范圍更廣的表達式:

    												
    														
    //p[class="greentea"]

    明白了嗎?甚至還能更進一步,選擇屬于 greentea 類的所有 元素而不論其元素類型是什么:

    												
    														
    //@class[.="greentea"]/..

    這個表達式可能看起來有點奇怪,但很容易解釋。首先,// 意味著從根元素開始選擇所有的元素(與后面的選擇器及條件匹配)而不論其嵌套的位置。然后 @class 選擇文檔中所有的 class 屬性。后面的 [.="greentea"] 有點神秘。="greentea" 部分容易理解,它用 greentea 匹配等式左側的值。在這里就是 .,這個標志還沒有見到過。但是再想一想目錄,.. 選擇父節點(或者父目錄),. 則選擇當前節點。因此 //@class[.="greentea"] 選擇值為 greentea 的所有 class 屬性。然后再移動到這些屬性所在的元素:

    												
    														
    //@class[.="greentea"]/..

    現在看起來有點不可思議,但是應該熟悉這類奇怪的表達式。當需要訪問特定的元素、屬性或節點集時它們很有用。

    計算

    隨著越來越多的使用屬性選擇器,最終將與處理節點一樣經常地使用值(來自屬性)。如果處理過非常典型的 XML,一定會遇到數字。XML 文檔常常把數字值放在屬性中(有時候在元素中)。因此這一節討論 /people/person[firstname = "John"]/@born/people/person/numChildren/text() 這類表達式的結果(當然,使用元素表示子女的個數不夠典型,不過就用下面的例子吧)。

    這時候您會發現 XPath 的計算能力很有用。可以像其他編程語言中那樣使用 +、-*。此外 div 用于除法,mod 則表示求模(兩數相除的余數)。比如,假設 XML 文檔中包含用四位數表示的出生年份,現在需要改成兩位數的形式,首先用下面的表達式取得實際的出生年份:

    												
    														
    /people/person/birthdate/@year

    這樣就得到了出生年份(可能是 1976 或者 1945)。然后只需要減去 1900:

    												
    														
    (/people/person/birthdate/@year) - 1900

    當然這種方法很有限,新千年出生的孩子和那些歷史人物都會造成這一公式的失敗。因此應該用 mod

    												
    														
    (/people/person/birthdate/@year) mod 100

    (順便說一下,應該告訴那些研究 Y2K 的人您省略了年份的前兩位數。)

    字符串技巧

    最后,XPath 還提供了一些很棒的字符串處理功能。XML 基本上都是文本,屬性值和元素中的數據通常是文本,因此不用奇怪 XPath 支持某些字符串操作。下面僅僅是 XPath 提供的處理字符串的少數函數:

    • string() 將數據轉換成字符串格式,如果還不是字符串的話。
    • starts-with(full-string, start-string) 返回一個 Boolean 值,檢查 full-string 是否以 start-string 開始。
    • contains(full-string, contains-string) 返回一個 boolean 值,檢查 full-string 是否包含 contains-string。
    • string-length(string) 返回 string 的長度。
    • normalize-space(string) 去掉 string 兩端和內部的空格。

    大部分函數的功能都很明確。starts-with("McLaughlin", "Mc") 返回 true,contains("McLaughlin", "augh") 同樣如此。string-length("Brett") 顯然返回 5,normalize-space(" Brett McLaughlin ") 則返回 "Brett McLaughlin"。是不是很簡單?當然這些可用于所有 XPath 表達式的返回值,比如 /html/body/p[class='greentea']。因此要獲取 清單 4p 的文本可用 normalize-space()

    												
    														
    normalize-space(/html/body/p[class='greentea'])

    更妙的是可用 string() 取出多個元素的文本。比如,如果希望取得 清單 4 所示 XHTML 中所有p 元素的所有 文本,可用:

    												normalize-space(string(//p))
    										

    分析最后一個例子可以了解很多內容:

    1. //p 選擇文檔中所有的 p 元素,無論其位于何處。
    2. string(//p) 獲取這些元素的內容組成一個大字符串。但是字符串中包含很多無用的空白,因此還要進一步處理。
    3. normalize-space(string(//p)) 規范化內容中的空白字符,得到您希望的文本。




    回頁首


    這是一篇關于數據綁定的文章嗎?

    現 在您可能已經忘記正在閱讀的是一篇關于數據綁定的文章。但是先不要忙于跟過去幾年中您讀過的其他 X* 文檔和 API 比較。您讀到的實際上是另一種數據綁定方法??紤]這樣一種觀點,數據綁定是在 Java 代碼中保留 XML 文檔邏輯(或者語義,如果您喜歡的話)意義。如果 XML 文檔中的 address 元素包含 street、citystate 子元素,想要用 getAddress().getStreet() 這樣的形式得到這些元素的值,比如:

    												
    														
    Address address = getAddress();
    System.out.println(address.getCity() + ", " + address.getState());

    這就是某種基本的數據綁定形式。但是在 XPath 中也能做到同樣的事!可以利用 address/street/text() 或者 /person[last-name="Gosling"]/address[@type="work"]/city 這樣的 XPath 表達式來得到街道名。初看起來與前一個例子不同,但是它仍然合理地使用了 XML 數據,您要的是 person、addressstreet 而不是第一個子元素第二個文本節點 或者屬性。這一點至關重要。XPath 按照邏輯而不是結構來處理 XML。基本上數據綁定也是如此,按照邏輯處理數據,而不用擔心其結構。

    為了避免誤導,需要指出使用 XPath 仍然需要對結構有所了解。比如,@ 運算符只用于屬性,因此必須知道 type(地址的一部分)用元素還是屬性表示。在傳統的數據綁定中,只需要調用 getAddress().getType() 而不需要管結構的層次。但是,這點小小的代價是值得的,因為不需要處理大量的生成類、額外的類路徑問題、等待封送和解除封送處理以及傳統數據綁定的其他缺點。

    只 剩下這個等式中需要在 Java 語言中增加的部分:接受 XML 文檔和 XPath 表達式,以 Java 友好的方式獲得表達式的結果。這些內容將在第 2 部分介紹,很快就要把 XPath 與 Java 編程中其他以 XML 為中心的工具一起使用了。很多情況下您會發現,與使用生成類和 JAXB 這樣的 API 的工具相比,XPath 是一種更好的 數據綁定工具。





    回頁首


    參考資料





    回頁首


    關于作者

    Brett McLaughlin 的照片

    Brett McLaughlin 從 Logo 時代就開始使用計算機。(還記得那個小三角嗎?)近年來他已經成為 Java 技術和 XML 社區最知名的作家和程序員之一。他曾經在 Nextel Communications 實現過復雜的企業系統,在 Lutris Technologies 編寫應用程序服務器,最近在 O'Reilly Media, Inc. 繼續撰寫和編輯這方面的圖書。在他的新書 Head Rush Ajax 中,Brett 與暢銷書作家 Eric 及 Beth Freeman 為 Ajax 帶來了獲獎的創新方法 Head First。最近的著作 Java 1.5 Tiger: A Developer's Notebook 是關于這一 Java 技術新版本的第一本書籍,經典著作 Java and XML 仍然是在 Java 語言中使用 XML 技術的權威圖書。


    posted on 2006-03-18 20:47 Vincent.Chen 閱讀(588) 評論(0)  編輯  收藏 所屬分類: AJAX

    主站蜘蛛池模板: 亚洲天堂中文字幕在线| 又粗又大又猛又爽免费视频| 亚洲av最新在线网址| 国产日韩精品无码区免费专区国产| 国产免费午夜a无码v视频| 国产AV无码专区亚洲AV蜜芽 | 亚洲中文久久精品无码ww16| 人体大胆做受免费视频| 亚洲视频在线一区二区| 高清永久免费观看| 亚洲乱码国产一区三区| 97在线视频免费| 2020年亚洲天天爽天天噜| 欧美日韩国产免费一区二区三区| 91亚洲国产成人久久精品网址| 免费看韩国黄a片在线观看| 亚洲AV无码一区二区三区网址| 亚洲av无码国产精品色在线看不卡| 国产99久久久久久免费看| 亚洲动漫精品无码av天堂| 最好看最新的中文字幕免费| 久久狠狠爱亚洲综合影院| 日韩一级视频免费观看| 国产VA免费精品高清在线| 亚洲色欲色欲综合网站| 国产免费AV片在线播放唯爱网 | 亚洲不卡中文字幕无码| 黄色免费网站网址| 日韩精品亚洲专区在线影视| 中文字幕亚洲乱码熟女一区二区 | 日韩精品无码一区二区三区免费| 亚洲另类春色国产精品| 免费大学生国产在线观看p| 日本免费污片中国特一级| 亚洲综合欧美色五月俺也去| 亚洲伦乱亚洲h视频| 亚洲毛片免费视频| 国产精品亚洲综合一区在线观看 | 久久久亚洲精品国产| 成人免费毛片视频| 两性色午夜免费视频|