Some HTML:
<div>
<div>
<button>
<svg xmlns="http://www.w3.org/2000/svg">
<path d="x" />
</svg>
</button>
</div>
<div>
<button> <!-- I want this -->
<svg xmlns="http://www.w3.org/2000/svg">
<path d="y" /> <!-- I have this -->
</svg>
</button>
</div>
</div>
I have the data (y
) to target the second path
, and then I want to get its ancestor button
.
I can target the path
element like this:
//svg/path[@d='y']
But I can't target its closest ancestor button
:
//svg/path[@d='y']/ancestor::button
A demo is here.
And if I try this in firefox or chromium devtools (for the page containing the above markup):
$x("//ancestor::button[1]", document.querySelector("path[d='y']"))
...it returns many results, not just the first ancestor button.
Inside the browser, and with the built-in XPath 1.0 support, I think you need to use namespaces to select the SVG elements e.g.
var namespaceResolver = function(prefix) {
if (prefix === 'svg')
return 'http://www.w3.org/2000/svg';
else
return null;
}
var path = document.evaluate('//svg:svg/svg:path[@d = "y"]', document, namespaceResolver, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue;
var ancestorButton = document.evaluate('ancestor::button[1]', path, namespaceResolver, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue;
console.log(ancestorButton.outerHTML);
<div>
<div>
<button>
<svg xmlns="http://www.w3.org/2000/svg">
<path d="x" />
</svg>
</button>
</div>
<div>
<button> <!-- I want this -->
<svg xmlns="http://www.w3.org/2000/svg">
<path d="y" /> <!-- I have this -->
</svg>
</button>
</div>
</div>
Or switch to SaxonJS and XPath 3.1 and use for instance a different default element namespace when looking for SVG and for HTML elements e.g.
const xhtmlNamespace = 'http://www.w3.org/1999/xhtml';
const svgNamespace = 'http://www.w3.org/2000/svg';
var path = SaxonJS.XPath.evaluate('//svg/path[@d = "y"]', document, { xpathDefaultNamespace : svgNamespace });
var ancestorButton = SaxonJS.XPath.evaluate('ancestor::button[1]', path, { xpathDefaultNamespace : xhtmlNamespace });
console.log(ancestorButton.outerHTML);
<script src="https://martin-honnen.github.io/Saxon-JS-2.5/SaxonJS2.js"></script>
<div>
<div>
<button>
<svg xmlns="http://www.w3.org/2000/svg">
<path d="x" />
</svg>
</button>
</div>
<div>
<button> <!-- I want this -->
<svg xmlns="http://www.w3.org/2000/svg">
<path d="y" /> <!-- I have this -->
</svg>
</button>
</div>
</div>