1

I know this question has been asked lot of times, but even after reading them i am not able to solve this issue.

Ask : I have one xml which has one node(GivenName) defined with a namespace(mpeg7) and declared at the top on the root element. I want to parse an attribute using xpath expression(//EpisodeOf/@crid) using javax xpath. Just to clear the code works when i remove this GivenName node from the xml.

XML :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TVAMain xmlns="urn:tva:metadata:2010" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:mpeg7="urn:tva:mpeg7:2008" publicationTime="2017-12-09T08:14:32Z" publisher="Gracenote, Inc." version="1"
         xml:lang="EN"
         xsi:schemaLocation="urn:tva:metadata:2010
                            http://developer.tmsapi.com/files/tva_metadata_3-1_v161.xsd
                            urn:tva:mpeg7:2008
                            http://developer.tmsapi.com/files/tva_mpeg7_2008.xsd">
    <ProgramDescription>
        <ProgramInformationTable>
            <ProgramInformation fragmentId="416885331" programId="someid">
                <BasicDescription>
                    <CreditsList>
                        <CreditsItem role="urn:mpeg:cs:RoleCS:2010:HOST" index="1">
                            <PersonName xml:lang="EN">
                                <mpeg7:GivenName xml:lang="EN">Azeb</mpeg7:GivenName>
                            </PersonName>
                        </CreditsItem>
                    </CreditsList>
                    <EpisodeOf type="Series" index="428" crid="crid://gn.tv/185326/SH007323210000"/>
                </BasicDescription>
            </ProgramInformation>
        </ProgramInformationTable>
    </ProgramDescription>
</TVAMain>

Code(In Kotlin) :

val xpath = XPathFactory.newInstance().newXPath()
xpath.namespaceContext = MyNamespaceContext()
val extractedValue = xpath.evaluate("",InputSource(StringReader(AboveXMLInStringVariable)), qName)}


class MyNamespaceContext : NamespaceContext {
        override fun getNamespaceURI(prefix: String?): String {
            println("checking for getnamespace")
            if (prefix == null) {
                throw  IllegalArgumentException("No prefix provided!");
            } else if (prefix.equals("mpeg7")) {
                return "http://developer.tmsapi.com/files/tva_mpeg7_2008.xsd";
            } else {
                return XMLConstants.NULL_NS_URI;
            }
        }
        override fun getPrefix(namespaceURI: String?): String {
            return ""
        }
        override fun getPrefixes(namespaceURI: String?): MutableIterator<Any?>? {
            return null
        }
    }

Getting error on xpath.evaluate function.

Caused by: org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 60; The prefix "mpeg7" for element ":GivenName" is not bound.
    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:466)
    ... 38 more

Question : I tried by giving NameSpaceContext to it, but it looks it is not using it. Suggestions ?

mdev
  • 1,366
  • 17
  • 23

1 Answers1

1

Several issues:

  • You do not appear to be enabling namespace awareness: DocumentBuilderFactory.setNamespaceAware(true).
  • Your XML has a default namespace: urn:tva:metadata:2010.
  • Your getNamespaceURI() is returning the wrong value for mpeg7; it should be returning urn:tva:mpeg7:2008.

See also: How does XPath deal with XML namespaces?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • I am using xpath.evaluate with InputSource parameter, which internally calls this statement Document document = getParser().parse( source ); In getParser() method it creates DocumentBuilderFactory with namespaceaware set to true. (com.sun.org.apache.xpath.internal.jaxp.XPathImpl). How does having a default namespace can cause this? It never printed my print statement of MyNamespaceContext class, so i didn't focus on that but thanks for correction. I will also look into the link provided. – mdev Dec 10 '17 at 21:45
  • Didn't mean to imply that the default namespace was the root cause of your problems -- just that you'll need to account for it in any XPaths written. – kjhughes Dec 10 '17 at 22:04
  • Are you sure your Kotlin is correct? Why don't you follow the Java example in [***How does XPath deal with XML namespaces?***](https://stackoverflow.com/q/40796231/290085) without Kotlin as a sanity check? – kjhughes Dec 10 '17 at 22:10