Stéphane Bruckert
Stéphane Bruckert

Reputation: 22903

XPath given by Chrome DevTools could not be found

As I was experimenting with some XPath SVG paths while answering another question about Selenium, I found out a strange behaviour with XPath on Chrome (I didn't try on some other browsers).

On http://www.amcharts.com/svg-maps/?map=usa, why doesn't that XPath work?

//*[@id="chartdiv"]/div/div[1]/svg/g[7]/g/g[1]

Whereas this one does?

//*[@id="chartdiv"]/div/div[1]/*[name()="svg"]/*[name()="g"][7]/*[name()="g"]/*[name()="g"][2]


I had to make the following changes:

The weird thing is that I got the first XPath by right-clicking the element HTML and copied the XPath from there.

enter image description here


I have another example on http://gmsgroup.com/municenter.asp where:

Here, /*[name()='a'][@title='Hawaii'] couldn't get <a title="Hawaii"></a>, why?

Upvotes: 4

Views: 3363

Answers (2)

Mathias M&#252;ller
Mathias M&#252;ller

Reputation: 22617

Namespaces can either be prefixed:

<root xmlns:ns="www.example.com"/>

or default namespaces:

<root xmlns="www.example.com"/>

SVG is in a default namespace. A path expression like /svg tells an XPath processor to look for an element that is called "svg" and that is in no namespace whatsoever. Therefore, this expression only matches:

<svg/>   or <svg xmlns=""/>

Using /*[name()='svg'] does only rule out a prefixed namespace. It still allows for an element that is called "svg" and that is in a default namespace, without a prefix. This second expression matches

<svg xmlns="http://www.w3.org/2000/svg"/>

but not

<ns:svg xmlns:ns="http://www.w3.org/2000/svg"/>

To prove this, consider the following XSLT stylesheet:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:template match="*[name() ='svg']">
        <hit/>
    </xsl:template>

</xsl:transform>

Applied to the following input, a shortened SVG document:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"/>

Results in:

<?xml version="1.0" encoding="UTF-8"?>
<hit/>

See for yourself online here.


EDIT (responding to your comment)

More clearly, does it mean that the SVG default namespace overrides the one from the page and therefore doesn't handle expressions such as [@title='Hawaii']?

The HTML elements themselves do not have a namespace - and SVG does not "override" the page's namespace. The default namespace on the svg element only applies to itself and all child elements (including the a[@title='Hawaii'] element inside it.

//*[@id='ext-gen203']/*[name()='svg']/*[name()='a'][@title='Hawaii']should be able to find the a element and I am very surprised it does not.

Where to find the specification for that default namespace?

If you mean default namespaces in general, look here: http://www.w3.org/TR/REC-xml-names/#scoping-defaulting. If you meant the SVG specification, study the following chapter of the SVG specification: http://www.w3.org/TR/SVG/struct.html.

Does it also mean that there isn't a better way of getting than //[@id='ext-gen203']/[name()='svg']/[name()='a']/[name()='path'][starts-wit‌​h(@d, 'M136.65')]/..?

The better way to do this is to register or declare those namespaces and thereby make them available for use in Xpath expressions by means of prefixes (as Martin Honnen has pointed out). Chrome Dev Tools is not my field of expertise, I cannot comment on how to do it there.

Upvotes: 7

Martin Honnen
Martin Honnen

Reputation: 167581

HTML5 and text/html allows you to mix HTML, MathML and SVG elements in one document and does not require you to use the namespaces associated with the different vocabularies. With XPath however you need to make sure you bind a prefix to the SVG namespace and use that prefix in your queries as in the DOM tree the SVG elements are in a different namespace than the HTML elements. Whether that is possible inside the developer tool I don't know but with an API there are usually ways to set up a namespace resolver that maps prefixes you want to use in your XPath expressions to namespace URLs.

Upvotes: 2

Related Questions