我正在使用Python + Selenium RC處理帶有css類「myclass」的可變數量的p元素的HTML頁面。如何迭代通過使用xpath匹配css類的DOM元素?
當我嘗試選擇與此XPath的每個節點:
//p[@class='myclass'][n]
(與NA自然數)
我得到的只有每n該CSS類的第一個p元素,不同的情況如果我通過選擇與p元素迭代:
//p[n]
有什麼辦法,我可以通過使用XPath的CSS類元素循環?
我正在使用Python + Selenium RC處理帶有css類「myclass」的可變數量的p元素的HTML頁面。如何迭代通過使用xpath匹配css類的DOM元素?
當我嘗試選擇與此XPath的每個節點:
//p[@class='myclass'][n]
(與NA自然數)
我得到的只有每n該CSS類的第一個p元素,不同的情況如果我通過選擇與p元素迭代:
//p[n]
有什麼辦法,我可以通過使用XPath的CSS類元素循環?
XPath 1.0不提供迭代構造。
迭代可以在託管XPath的語言中對所選節點集執行。
實例:
在XSLT 1.0:
<xsl:for-each select="someExpressionSelectingNodes">
<!-- Do something with the current node -->
</xsl:for-each>
在C#:
using System;
using System.IO;
using System.Xml;
public class Sample {
public static void Main() {
XmlDocument doc = new XmlDocument();
doc.Load("booksort.xml");
XmlNodeList nodeList;
XmlNode root = doc.DocumentElement;
nodeList=root.SelectNodes("descendant::book[author/last-name='Austen']");
//Change the price on the books.
foreach (XmlNode book in nodeList)
{
book.LastChild.InnerText="15.95";
}
Console.WriteLine("Display the modified XML document....");
doc.Save(Console.Out);
}
}
的XPath 2.0有它自己的iteration construct:
for $varname1 in someExpression1,
$varname2 in someExpression2,
. . . . . . . . . . .
$varnameN in someExpressionN
return
SomeExpressionUsingTheVarsAbove
也許我的問題還不夠清楚,但我看不出你的答案與它有關。 我可以使用[n]結尾從多個簡單匹配中選擇一個元素,例如// p [n]遍歷所有p元素。我試圖迭代只有那些具有某個類的p元素時,我的問題就開始了。 – 2010-07-17 19:12:13
誰低估了這個答案,請提出並說明原因?是因爲天氣不好還是因爲你是一個無能的懦夫?我想這是後者...... – 2010-07-17 23:05:31
@GJ:爲什麼,只需從你的表達式中選擇someExpressionSelectingNodes('// p [@ class ='myclass'''')來選擇你要迭代的節點。我已經提供了兩個示例:如何組織迭代 - 使用兩種不同的託管語言。它必須是您使用的託管語言中類似的東西。 – 2010-07-17 23:52:30
也許你所有的這個類的div都在同一個級別,所以// p [@ class ='myclass']你會收到帶有指定類的段落數組。所以你應該使用索引遍歷它,例如 // p [@ class ='myclass'] [1],//p[@class='myclass'][2],...//p[@ class ='myclass'] [last()]
我不認爲你使用「索引」是因爲它的真正目的。在這個選擇中的//p[selection][index]
語法實際上告訴你它的父應該是哪個元素......所以//p[selection][1]
是說你選擇的p必須是它的父親的第一個孩子。 //p[selection][2]
是說它必須是第二個孩子。根據你的html,這可能不是你想要的。
鑑於您使用的是Selenium和Python,有幾種方法可以做到您想要的,您可以查看this question以查看它們(這裏有兩個選項,一個用於selenium Javascript,另一個用於使用服務器端硒調用)。
在XPath下,'[n]'謂詞(這是'[position()= n]'的簡稱)意思是「只選擇上下文組的第n個節點」。上下文組是由謂詞前面的XPath表達式指定的節點集合。這可能與也可能不涉及其在特定父母的兄弟姐妹中的順序。在這種情況下它沒有。 – LarsH 2010-09-13 16:40:53
@LarsH - 是的,你有我......我無法解釋得那麼好。你是否同意鏈接的SO答案提供了正確的答案類型(也與Dimitre說的非常相似)......如果不是,我可能會刪除這個答案。 – Ryley 2010-09-13 18:54:39
我不確定鏈接的答案是否相關。實際上,我似乎回想起我有限和很久以前的Selenium經驗,Selenium並不是真正的XPath,而是一個有限的子集,甚至可能不完全正確。所以這可能是OP的問題。就我所知,Selenium中的'[n]'按照你說的方式工作,而不是XPath規範說的方式。就像我在對問題的評論中所說的那樣,如果我們看到@Gj迭代的上下文,我們可能能夠解決問題。 – LarsH 2010-09-13 19:15:57
下面是一個C#代碼片段,可以幫助你。
這裏的關鍵是硒功能GetXpathCount()
。它應該返回您正在查找的Xpath表達式的出現次數。
您可以在XPather或任何其他Xpath分析工具中輸入//p[@class='myclass']
,以便確實可以驗證是否返回多個結果。然後你只需遍歷代碼中的結果。
就我而言,這是UL中所有需要迭代的列表項 - 即.e. //li[@class='myclass']/ul/li
- 所以根據您的要求應該是這樣的:
int numProductsInLeftNav = Convert.ToInt32(selenium.GetXpathCount("//p[@class='myclass']"));
List<string> productsInLeftNav = new List<string>();
for (int i = 1; i <= numProductsInLogOutLeftNav; i++) {
string productName = selenium.GetText("//p[@class='myclass'][" + i + "]");
productsInLogoutLeftNav.Add(productName);
}
現在,我在這個問題再看看,我認爲真正的問題不是出在迭代,但在使用//
。
這是一個常見問題:
//p[@class='myclass'][1]
選擇具有class
屬性具有值"myclass"
每p
元件,這是它的父的第一個這樣的孩子。因此這個表達式可以選擇許多元素,其中沒有一個真的是文檔中的第一個這樣的元素p
。
當我們想要得到的第一p
元素滿足上述謂詞文檔中,一個正確的表達是:
(//p)[@class='myclass'][1]
記住:該[]
操作具有更高的優先級(優先級),比//
的縮寫。 無論您需要爲由//
選擇的節點編制索引,始終要將表達式編入索引到括號中。
下面是一個示範:
<nums>
<a>
<n x="1"/>
<n x="2"/>
<n x="3"/>
<n x="4"/>
</a>
<b>
<n x="5"/>
<n x="6"/>
<n x="7"/>
<n x="8"/>
</b>
</nums>
XPath表達式:
//n[@x mod 2 = 0][1]
選擇以下節點:
<n x="2" />
<n x="6" />
XPath表達式:
(//n)[@x mod 2 = 0][1]
選擇完全相同的第一n
元件在文檔中與想要的屬性:
<n x="2" />
嘗試此第一與下列變換:
<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:copy-of select="//n[@x mod 2 = 0][1]"/>
</xsl:template>
</xsl:stylesheet>
並且結果是兩個節點。
<n x="2" />
<n x="6" />
現在,改變XPath表達式如下,然後再試一次:
<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:copy-of select="(//n)[@x mod 2 = 0][1]"/>
</xsl:template>
</xsl:stylesheet>
,其結果是我們真正想要 - 文檔中的第一個這樣的n
元素:
<n x="2" />
好問題(+1)。請參閱我的答案,以獲取XPath表達式選擇的節點集中迭代的解釋和示例。 – 2010-07-17 16:35:38
這個問題並不完全。你用什麼技術/語言來「處理」你的頁面?你想在XPath中「迭代」到底是什麼? (XPath是*選擇*語言,而不是*處理*語言。迭代作爲一個概念在這裏沒有多大意義。)請解釋一下。 – Tomalak 2010-07-17 16:54:12
@Gj它可能有助於顯示嘗試迭代XPath表達式所選節點集的Python或Selenium RC代碼。 – LarsH 2010-09-13 16:44:25