XQuery - Query Element Hierarchies
- Last Updated: May 20, 2026
- 2 minute read
- MarkLogic Server
- Version 12.0
- Documentation
Use this code to insert a new document (along with permissions) into the Documents database:
(: insert document with permissions => run against Documents database :)
xquery version "1.0-ml";
xdmp:document-insert(
"hierarchy.xml", <root>
<title>Title of the Document</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of the document contents
<secret>Only role having "secret" can read this
<top-secret>Only role having "top-secret" can read this
</top-secret>
</secret>
</executive-summary>
<content>Contents of document
<top-secret>Only role with "top-secret" can read this
<secret>Only role with "secret" can read this</secret>
</top-secret>
Unclassified content
</content>
</root>,
(xdmp:permission("els-role-1", "read"), xdmp:permission("els-role-2", "read"),
xdmp:permission("els-role-1", "update"), xdmp:permission("els-role-2", "update")))
Add protected paths with permissions for roles to the Security database:
(: add protected paths -> run against the Security database :)
xquery version "1.0-ml";
import module namespace sec="http://marklogic.com/xdmp/security"
at "/MarkLogic/security.xqy";
sec:protect-path("secret", (), (xdmp:permission("els-role-2", "read"))),
sec:protect-path("top-secret", (), (xdmp:permission("els-role-1", "read")))
=>
Returns two numbers representing the protected paths
Note: Adding, unprotecting, or changing permissions on protected paths will trigger reindexing.
Test this example in the context of the different els-users. This first query uses the context of els-user-1:
(: run this against the Documents database :)
xdmp:eval('fn:doc("hierarchy.xml")',(),
<options xmlns="xdmp:eval">
<user-id>{xdmp:user("els-user-1")}</user-id>
</options>
)
=>
<root>
<title>Title of the Document
</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
</executive-summary>
<content>Contents of document
<top-secret>Only role with "top-secret" can read this</top-secret>
Unclassified content</content>
</root>
The “top-secret” role (els-user-1) cannot see the elements marked with “secret”, only those that have no protected paths or marked with the protected path for “top-secret”. Next, run the query in the context of els-user-2:
(: run this against the Documents database :)
xdmp:eval('fn:doc("hierarchy.xml")',(),
<options xmlns="xdmp:eval">
<user-id>{xdmp:user("els-user-2")}</user-id>
</options>
)
=>
<root>
<title>Title of the Document</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<secret>Only role having "secret" can read this</secret></executive-summary>
<content>Contents of document
Unclassified content</content>
</root>
Notice that even though in the original document there is an element “secret” within the “top-secret” contents of the document, it is a child of the “top-secret” element and therefore hidden to users without the “top-secret” role.
The els-user-1 (“top-secret”) cannot see the “secret” content unless you add the els-role-2 to els-user-1. When you add the role, els-user-1 will be able to see both the “secret” and “top-secret” elements.
If you run the query as els-user-3, the query returns an empty sequence. The els-user-3 from the previous query does not have permission to even see the document.