javascriptxpathxmlhttprequestxmldom

XPath within document.evaluate returns empty if filtering by xml:id


I have this .xml:

[...]<person xml:id="pe_054">
                   <persName>
                      <forename>Robert</forename>
                      <surname>Thomas</surname>
                   </persName>
 </person>[etc]

I have this JavaScript:

[...]function resolver() {
return 'http://www.tei-c.org/ns/1.0';
}
Connect.open("GET", "data/persons_places.xml", false);
Connect.setRequestHeader("Content-Type", "text/xml");
Connect.send(null);
var xmldoc = Connect.responseXML;
const surname = xmldoc.evaluate('//tei:person/tei:persName/tei:surname', xmldoc, resolver, XPathResult.STRING_TYPE, null)[...]

which works as expected, i.e. it returns the text content of the first 'surname' node. I need, though, to get a specific surname via the @xml:id attribute. Therefore, if I edit the XPath to this:

const surname = xmldoc.evaluate('//tei:person[@xml:id='pe_001']/tei:persName/tei:surname', xmldoc, resolver, XPathResult.STRING_TYPE, null)

the code returns an empty string. In the console.log I get:

XPathResult { resultType: 2, stringValue: "", invalidIteratorState: false }

stringValue does get populated if I don't filter by @xml:id. I'm at a loss: I tried making it workin by escapint the @, the brackets, the equals, nothing. Can anybody help me please?


Solution

  • Thanks to @supputuri I realised that it was just an issue with the xml namespace. So, the working code is:

    function nsResolver(prefix) {
      var ns = {
        'xml' : 'http://www.w3.org/XML/1998/namespace',
        'tei': 'http://www.tei-c.org/ns/1.0'
      };
      return ns[prefix] || null;
    }
    const Connect = new XMLHttpRequest();
    
    Connect.open("GET", "data/persons_places.xml", false);
    Connect.setRequestHeader("Content-Type", "text/xml");
    Connect.send(null);
    var xmldoc = Connect.responseXML;
    const surname = xmldoc.evaluate('string(//tei:person[@xml:id="pe_054"]/tei:persName/tei:surname)', xmldoc, nsResolver, XPathResult.STRING_TYPE, null)