Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JDOM2 xpath finding nodes within a different namespace

Tags:

java

xpath

jdom-2

I'm attempting to use JDOM2 in order to extract the information I care about out of a XML document. How do I get a tag within a tag?

I have been only partially successful. While I have been able to use xpath to extract <record> tags, the xpath query to extract the title, description and other data with in the record tags has been returning null.

I've been using Xpath successfully to extract <record> tags out of the document. To do this I use the follwing xpath query: "//oai:record" where the "oai" namespace is a namespace I made up in order to use xpath.

You can see the XML document I'm parsing here, and I've put a sample below: http://memory.loc.gov/cgi-bin/oai2_0?verb=ListRecords&set=cwp&metadataPrefix=oai_dc

<record>
    <header>
        <identifier>oai:lcoa1.loc.gov:loc.pnp/cph.3a02293</identifier>
        <datestamp>2009-05-27T07:22:37Z</datestamp>
        <setSpec>cwp</setSpec>
        <setSpec>lcphotos</setSpec>
    </header>
    <metadata>
        <oai_dc:dc xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/                          http://www.openarchives.org/OAI/2.0/oai_dc.xsd">
            <dc:title>Jubal A. Early</dc:title>
            <dc:description>This record contains unverified, old data from caption card.</dc:description>
            <dc:date>[between 1860 and 1880]</dc:date>
            <dc:type>image</dc:type>
            <dc:type>still image</dc:type>
            <dc:identifier>http://hdl.loc.gov/loc.pnp/cph.3a02293</dc:identifier>
            <dc:language>eng</dc:language>
            <dc:rights>No known restrictions on publication.</dc:rights>
        </oai_dc:dc>
    </metadata>
</record>

If you look in the larger document you will see that there is never a "xmlns" attribute listed on any of the tags. There is also the matter of there being three different namespaces in the document ("none/oai", "oai_dc", "dc").

What is happening is that the xpath is matching nothing, and evaluateFirst(parent) is returning null.

Here is some of my code to extract the title, date, description etc. out of the record element.

    XPathFactory xpf = XPathFactory.instance();
    XPathExpression<Element> xpath = xpf.compile("//dc:title",
                  Filters.element(), null,
                  namespaceList.toArray(new Namespace[namespaceList.size()]));
    Element tag = xpath.evaluateFirst(parent);

    if(tag != null)
    {
        return Option.fromString(tag.getText());
    }

    return Option.none();

Any thoughts would be appreciated! Thanks.

like image 559
Prichmp Avatar asked Oct 30 '22 13:10

Prichmp


1 Answers

In your XML, dc prefix mapped to the namespace uri http://purl.org/dc/elements/1.1/, so make sure you declared the namespace prefix mapping to be used in the XPath accordingly. This is part where the namespace prefix declare in your XML :

<oai_dc:dc
    xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/
                         http://www.openarchives.org/OAI/2.0/oai_dc.xsd">

XML parser only see the namespace explicitly declared in the XML, it won't try to open the namespace URL since namespace is not necessarily a URL. For example, the following URI which I found in this recent SO question is also acceptable for namespace : uuid:ebfd9-45-48-a9eb-42d

like image 182
har07 Avatar answered Nov 15 '22 03:11

har07