使用XPath選擇帶通配符的屬性

c# html html-agility-pack xpath

我得到了需要解析的HTML,我正在使用C#和Html Agility Pack Library來選擇節點。我的html看起來像是:

<input data-translate-atrr-placeholder="FORGOT_PASSWORD.FORM.EMAIL">

要么 :

<h1 data-translate="FORGOT_PASSWORD.FORM.EMAIL"></h1>

其中data-translate-attr-****是我需要找到的新屬性模式

我可以使用這樣的東西:

//[contains(@??,'data-translate-attr')]

但不幸的是,這只會搜索INSIDE屬性的值。 如何使用通配符查找屬性本身?

更新: @Mathias Muller

HtmlAgilityPack.HtmlDocument htmlDoc    
// this is the old code (returns nodes)
var nodes = htmlDoc.DocumentNode.SelectNodes("//@data-translate");  
// these suggestions return no nodes using the same data
var nodes = htmlDoc.DocumentNode.SelectNodes("//@*[contains(name(),'data-translate')]");  
var nodes = htmlDoc.DocumentNode.SelectNodes("//@*[starts-with(name(),'data-translate')]");

更新2

這似乎是一個Html Agility Pack問題而不是XPath問題,我使用chrome來測試我的XPath表達式,所有以下工作都在chrome中但不在Html Agility Pack中:

//@*[contains(local-name(),'data-translate')]
//@*[starts-with(name(),'data-translate')]
//attribute::*[starts-with(local-name(.),'data-translate')]

我的解決方案

我最後只是以老式的方式做事......

var nodes = htmlDoc.DocumentNode.SelectNodes("//@*");

if (nodes != null) {
    foreach (HtmlNode node in nodes) {
        if (node.HasAttributes) {
            foreach (HtmlAttribute attr in node.Attributes) {
                if (attr.Name.StartsWith("data-translate")) {
                    // code in here to handle translation node
                }
            }
        }
    }
}

一般承認的答案

使用XPath函數contains()starts-with() 。你需要一個XPath表達式

//@*[contains(name(),'data-translate')]

也許

//@*[starts-with(name(),'data-translate')]

它實際上檢索屬性節點。上面, @*是您要查找的屬性通配符。


熱門答案

而不是使用name() ,使用local-name()例如:

var nodes = htmlDoc.DocumentNode.SelectNodes("//@*[starts-with(local-name(),'data-translate')]");

區別在於name()應該為您提供帶有前綴的屬性名稱,例如xml中的命名空間, local-name()將在那裡發出該前綴,在您的情況下name()local-name()應該以同樣的方式工作,因為它的HTML和沒有名稱空間,但似乎他們沒有,它可能是一個錯誤。

測試:

    var html = "<h3 x='foo'></h3>";
    var doc = new HtmlAgilityPack.HtmlDocument();
    doc.LoadHtml(html);
    var ElementByName = doc.DocumentNode.SelectSingleNode("//*[name()='h3']");                //Works
    var ElementByLocalName = doc.DocumentNode.SelectSingleNode("//*[local-name()='h3']");     //Works
    var ElementByAttributeLocalName = doc.DocumentNode.SelectSingleNode("//*[@*[local-name()='x']]"); //Works
    var ElementByAttributeName = doc.DocumentNode.SelectSingleNode("//*[@*[name()='x']]");  //Does NOT

    //Mathias Way
    var ElementByAttributeLocalName_ = doc.DocumentNode.SelectSingleNode("//@*[local-name() = 'x']"); //Works
    var ElementByAttributeName_ = doc.DocumentNode.SelectSingleNode("//@*[name() = 'x']");  //Does NOT


許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因