Home > Software engineering >  Getting an attribute value from XBRL file using XPath
Getting an attribute value from XBRL file using XPath

Time:03-09

I have this xbrl.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xml:lang="nl" xmlns:bd-i="http://www.nltaxonomie.nl/nt15/bd/20201209/dictionary/bd-data" xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:iso4217="http://www.xbrl.org/2003/iso4217" xmlns:xbrli="http://www.xbrl.org/2003/instance">
    <link:schemaRef xlink:type="simple" xlink:href="http://www.nltaxonomie.nl/nt15/bd/20201209/entrypoints/bd-rpt-ob-aangifte-2021.xsd"/>
    <xbrli:unit id="EUR">
        <xbrli:measure>iso4217:EUR</xbrli:measure>
    </xbrli:unit>
</xbrli:xbrl>

and I want to get the value of xmlns:link attribute.

This the code that I am using:

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.util.Iterator;

public class test {
    public static void main(String[] args) {
        try {
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            documentBuilderFactory.setNamespaceAware(true);

            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

            Document xmlDocument = documentBuilder.parse("src/resources/xbrl.xml");

            XPathFactory xPathFactory = XPathFactory.newInstance();

            final String namespace = "http://www.xbrl.org/2003/instance";

            XPath xPath = xPathFactory.newXPath();
            xPath.setNamespaceContext(new NamespaceContext() {   
                public String getNamespaceURI(String prefix) {
                    if (prefix.equals("xbrli")) {
                        return namespace;
                    } else {
                        return null;
                    }
                }

                public String getPrefix(String namespaceURI) {
                    return null;
                }

                public Iterator<String> getPrefixes(String namespaceURI) {
                    return null;
                }
            });
            String expression = "//xmlns:xlink";
            XPathExpression xPathExpression = xPath.compile(expression);
            Object result = xPathExpression.evaluate(xmlDocument, XPathConstants.NODESET);
            NodeList nodeList = (NodeList) result;
            if (nodeList.getLength() > 0) {
                for (int i = 0; i < nodeList.getLength(); i  ) {
                    System.out.println("["   i   "]-1-NodeValue: "   nodeList.item(i).getNodeValue());
                    System.out.println("["   i   "]-2-NodeName: "   nodeList.item(i).getNodeName());
                    System.out.println("["   i   "]-3-TextContent: "   nodeList.item(i).getTextContent());
                    System.out.println("["   i   "]-4-LocalName: "   nodeList.item(i).getLocalName());
                    System.out.println("["   i   "]-5-NamespaceURI: "   nodeList.item(i).getNamespaceURI());
                }
                System.out.println("Printed nodes");
            } else {
                System.out.println("I got nothing");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("MESSAGE: "   ex.getMessage());
        }
    }
}

The result is :(

I got nothing.

If I tried to get the value of another attribute of the XBRLfile, I can get it without any issues. But If I tried to get the value that i mentioned above then I get no thing.

This is a photo of my Intellij: enter image description here

Why I can not get the value of the attribute?

CodePudding user response:

The xmlns: attributes are special, as they are declaring namespace bindings for use elsewhere in the document. A namespace aware XML processor will consume these attributes automatically, and use them to associate prefixed elements and attributes with the corresponding namespace URI. You may find that if you change setNamespaceAware(true) to setNamespaceAware(false) the xmlns attributes are accessible, but I wouldn't recommend doing that.

Why do you want to get the value of that attribute? You should write your code in terms of namespace URIs, and let your namespace-aware XML processor take care of resolving namespace prefixes into URIs.

CodePudding user response:

Since XPath 3.0 you can only query indirectly for the namespaces that have been declared with xmlns:.

For example, to query for the namespace of the xmlns:xlink declaration, you could query for any node (element or attribute) that uses the prefix xlink: and get the namespace from there (depending on the processor, this may be an expensive operation):

distinct-values((//@xlink:*, //xlink:*)/namespace-uri())

Note: alternatively, direct querying of namespace nodes might still work up to XPath 2.0 (since then the namespace axis has been deprecated):

distinct-values(//namespace::xlink)

Note 2: namespace declarations are scoped. There might be several different namespace declarations for the same prefix in one XML document.

  • Related