我正在使用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