Come selezionare una tabella che contiene determinate parole chiave - c # - xpath - htmlagilitypack

c# html-agility-pack keyword select xpath

Domanda

Devo raccogliere informazioni da una pagina prodotto che non ha alcuna classe o ID. Sto usando htmlagilitypack e c # 4.0.

Ci sono molte tabelle in questo codice sorgente della pagina prodotto. La tabella dei prezzi contiene la stringa "KDV". Quindi mi piacerebbe avere questa tabella contenente la stringa "KDV". Come lo posso fare ?

L'xpath in basso selezionerebbe tutte le tabelle, ad esempio

string srxPathOfCategory = "//table";
var selectedNodes = myDoc.DocumentNode.SelectNodes(srxPathOfCategory);

Il codice sottostante seleziona la tabella ma inizia dalla maggior parte della tabella esterna. Devo selezionare la maggior parte della tabella interna che contiene quella determinata stringa

//table[contains(., ' KDV')]

c #, xpath, htmlagilitypack

Risposta accettata

Il codice sottostante seleziona la tabella ma inizia dalla maggior parte della tabella esterna. Devo selezionare la maggior parte della tabella interna che contiene quella determinata stringa

Usa :

//table
    [not(descendant::table) 
   and 
     .//text()[contains(., ' KDV')]
    ]

Ciò seleziona qualsiasi table nel documento XML che non ha un discendente della table e che ha un discendente del nodo di testo che contiene la stringa " KDV" .

In generale, l'espressione sopra potrebbe selezionare molti di questi elementi di table .

Se vuoi che venga selezionato solo uno di essi (diciamo il primo), usa questa espressione XPath - nota le parentesi :

   (//table
        [not(descendant::table) 
       and 
         .//text()[contains(., ' KDV')]
        ]
    )[1]

Ricorda : se vuoi selezionare il primo elemento someName nel documento, usare questo (come nella risposta attualmente accettata) è sbagliato:

//someName[1]

Questa è la seconda maggior parte delle FAQ in XPath (dopo quella di come selezionare elementi con nomi non prefissati in un documento XML con uno spazio dei nomi predefinito).

L'espressione sopra in realtà seleziona qualsiasi elemento someName nel documento, ovvero il primo figlio del suo genitore - provalo.

Il motivo di questo comportamento non intuitivo è dovuto al fatto che l'operatore XPath [] ha una precedenza (priorità) più alta che // pseudo-operatore.

L'espressione corretta che seleziona realmente solo il primo elemento someName (in qualsiasi documento XML), se tale esiste è:

(//someName)[1]

Qui le parentesi sono usate per sovrascrivere esplicitamente la precedenza dell'operatore XPath predefinito.


Risposta popolare

Potrebbe esserci un modo più efficiente per farlo. Ad ogni modo, questo è l'intero codice che ho usato per il tuo caso e funziona per me:

        HtmlDocument doc = new HtmlDocument();
        string url = "http://www.pratikev.com/fractalv33/pratikEv/pages/viewProduct.jsp?pInstanceId=3138821";
        using (var response = (WebRequest.Create(url).GetResponse()))
        {
            doc.LoadHtml(new StreamReader(response.GetResponseStream()).ReadToEnd());
        }
        /*There is an bug in the xpath used here. Should have been 
          (//table/tr/td/font[contains(.,'KDV')])[1]/ancestor::table[2] 
          See Dimitre's answer for an explanation and an alternative / 
          more generic / (needless to say) better approach */
        string xpath = "//table/tr/td/font[contains(.,'KDV')][1]/ancestor::table[2]"; 
        HtmlNode table = doc.DocumentNode.SelectSingleNode(xpath);



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché