3

I am new to Marklogic and My Requirement is, I have XML document in Marklogic Database containing multiple elements.

 ** Example :**    

<tXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Header>
        <Source>Source1</Source>
        <Action_Type>Action_Type1</Action_Type>
        <Sequence_Number>Sequence_Number1</Sequence_Number>
    </Header>
</tXML>

When i pass "Sequence_Number"it should return /tXML/Header/Sequence_Number and it is possible to have "Sequence_Number" element multiple times.

Please tell me whether it is possible using Marklogic XQuery/Java API or i need to uses any third party API to obtain this result.

Dave Cassel
  • 8,352
  • 20
  • 38
DevNinja
  • 1,459
  • 7
  • 10

2 Answers2

4

It probably won't perform well on large documents, but you could use string matching on element names to find the elements, and then use xdmp:path to get the corresponding XPath for that document. Something like:

xquery version "1.0-ml";

let $xml := document {
<tXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Header>
        <Source>Source1</Source>
        <Action_Type>Action_Type1</Action_Type>
        <Sequence_Number>Sequence_Number1</Sequence_Number>
    </Header>
</tXML>
}
let $elem-name := "Sequence_Number"
let $elems := $xml//*[local-name() eq $elem-name]
return $elems ! xdmp:path(.)

HTH!

grtjn
  • 20,254
  • 1
  • 24
  • 35
  • 1
    Even shorter (maybe a little more efficient) would be to avoid letting a variable with the matched elements, and simply return the sequence of XPaths: `return $xml//*[local-name() eq $elem-name]/xdmp:path(.)` – Mads Hansen Mar 24 '18 at 23:36
0

If you pass the String "Sequence_Number" then how could it know which of the Sequence_Number siblings to get the XPath of? You could be talking about the first occurrence or maybe the second or third, it wont know. Given just a tagName, it can't know which occurrence to get the XPath for.

That said, the below method will give you the general XPath to where an element lives. You just need to get the org.w3c.dom.Element first, which can be gotten from the org.w3c.dom.Document.

public static String getXPathOfElement(org.w3c.dom.Element el) {
    Objects.requireNonNull(el);
    LinkedList<String> list = new LinkedList<>();
    for (Node n = el; n != null; n = n.getParentNode()) {
        if (n.getNodeType() == Node.ELEMENT_NODE)
            list.push(n.getNodeName());
        else
            list.push("");
    }
    return String.join("/", list);
}


public static void main(String[] args)
        throws ParserConfigurationException, SAXException, IOException {

    // Get an input stream of your Xml somehow
    String xml =
            "<tXML xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
            + "<Header>"
            + "<Source>Source1</Source>"
            + "<Action_Type>Action_Type1</Action_Type>"
            + "<Sequence_Number>Sequence_Number1</Sequence_Number>"
            + "</Header>"
            + "</tXML>";

    java.io.InputStream xmlInputStream = new java.io.ByteArrayInputStream(xml.getBytes());

    // Get the Document from the xml InputStream
    javax.xml.parsers.DocumentBuilderFactory docBuilderFact =
            javax.xml.parsers.DocumentBuilderFactory.newInstance();
    javax.xml.parsers.DocumentBuilder docBuilder = docBuilderFact.newDocumentBuilder();
    org.w3c.dom.Document doc = docBuilder.parse(xmlInputStream);

    // Get the Element you want the general XPath of
    // In this case just find the first one with a certain tag in the Document
    org.w3c.dom.Element el =
            (org.w3c.dom.Element) doc.getElementsByTagName("Sequence_Number").item(0);

    System.out.println(getXPathOfElement(el));
}
xtratic
  • 4,600
  • 2
  • 14
  • 32
  • Thanks xtratic for you reply but i can't go with this (org.w3c.dom.Element) doc.getElementsByTagName("Sequence_Number").item(0); and as i mentioned that Sequence_Number can repeat multiple times under multiple parent nodes so i need xpath of all the occurrences of Sequence_Number – DevNinja Mar 23 '18 at 02:07