Search code examples
javascriptxmlxsltxpathecma

How do I write a conditional xpath select for specific nodes?


So I have a userscript added on chrome, autopagerizer.

currently I'm using

//div[@class=\'entry-content\']/p[contains(.,\'chapter\') or contains(.,\'Chapter\') or preceding-sibling::p[contains(.,\'Chapter\')] and (following-sibling::p[contains(.,\'Translator Ramblings\')] or following-sibling::p[contains(.,\'Translating Ramblings\')] or following-sibling::p[contains(.,\'Ramblings\')] or following-sibling::p[starts-with(.,\'Translator\')] or following-sibling::p[starts-with(.,\'Translating\')])] 

I want a conditional argument where when the above code doesn't resolve anything, it would select

//h3[contains(.,\'Share this\')]

Instead. I Only want the h3 to be selected when that's the case. I can't figure out how to write this in xpath, I've looked up the other related questions and they don't resolve this issue. If I can't solve this with xpath, how would I solve this with javascript? I'm using grease monkey on chrome.


Solution

  • Basically, the pattern to achieve what you explained using pure XPath 1.0 could be as follows :

    expression1 | expression2[not(expression1)]
    

    So, in the context of your question :

    • expression1 (truncated): //div[@class=\'entry-content\']/p[...]
    • expression2: //h3[contains(.,\'Share this\')]
    • solution:

      //div[@class=\'entry-content\']/p[...]  | 
        //h3[contains(.,\'Share this\')]
            [not(//div[@class=\'entry-content\']/p[...])]
      

    This could be much cleaner if implemented with help of Javascript. Simply execute expression1, and if the result is of length 0 then execute expression2.