JavaScript - Matching by Paths or Attributes
- Last Updated: May 20, 2026
- 3 minute read
- MarkLogic Server
- Version 12.0
- Documentation
This next example shows how protected paths can be used with fn.contains() and fn.matches(). The example uses the same roles from the previous example, adding a new role (els-role-3).
First unprotect the protected paths from the previous example:
// unprotect protected paths -> run against the Security database
declareUpdate();
var security = require('/MarkLogic/security.xqy');
security.unprotectPath('secret', []),
security.unprotectPath('top-secret', [])
Note: Adding, unprotecting, or changing permissions on protected paths will trigger reindexing.
Create a new role els-role-3 and add els-user-3 to the role. See Create Roles and Create Users and Assign Roles for details.
Add a new document to the Documents database:
// insert document and permissions -> run this against the Documents database
declareUpdate();
var perms = [xdmp.permission("els-role-1", "read"), xdmp.permission("els-role-2", "read"),
xdmp.permission("els-role-3", "read"), xdmp.permission("els-role-1", "update"),
xdmp.permission("els-role-2", "update"), xdmp.permission("els-role-3", "update")
];
xdmp.documentInsert(
"attributes.xml", xdmp.unquote(`
<root>
<title>Document Title</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<info attr="EU">Only role with "EU" attribute can read this summary </info>
<info attr="UK">Only role with "UK" attribute can read this summary </info>
<info attr="US">Only role with "US" attribute can read this summary </info>
</executive-summary>
<content>Contents of document
Unclassified content
<notes>
<info attr="EU">Only role with "EU" attribute can read this content</info>
<info attr="UK">Only role with "UK" attribute can read this content</info>
<info attr="US">Only role with "US" attribute can read this content</info>
</notes>
</content>
</root>
`), {permissions: perms})
Add the new protected paths with permissions for roles to the Security database:
// add new protected paths -> run against the Security database
declareUpdate();
var security = require('/MarkLogic/security.xqy');
security.protectPath("//info[fn:matches(@attr, 'US')]", [],[xdmp.permission("els-role-1","read", "element")]),
security.protectPath("//info[fn:matches(@attr, 'UK')]", [],[xdmp.permission("els-role-2", "read", "element"),
xdmp.permission("els-role-3", "read", "element")]),
security.protectPath("//info[fn:matches(@attr, 'EU')]", [],
[xdmp.permission("els-role-3", "read", "element")])
=>
Returns one number representing the protected paths
Note: Adding or changing permissions on protected paths will trigger reindexing.
Run the same queries as before, first in the context of els-user-1, who has a role that can see the “US” attribute:
// run this query against the Documents database
xdmp.eval("fn.doc('attributes.xml')", null,
{
"userId" : xdmp.user("els-user-1")
});
=>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Document Title</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<info attr="US">Only role with "US" attribute can read this summary</info>
</executive-summary>
<content>Contents of document
Unclassified content
<notes>
<info attr="US">Only role with "US" attribute can read this content</info>
</notes></content>
</root>
Next modify the query to run in the context of els-user-2, who has a role that can see the “UK” attribute:
// run this query against the Documents database
xdmp.eval("fn.doc('attributes.xml')", null,
{
"userId" : xdmp.user("els-user-2")
});
=>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Document Title</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<info attr="UK">Only role with "UK" attribute can read this summary</info></executive-summary>
<content>Contents of document
Unclassified content
<notes>
<info attr="UK">Only role with "UK" attribute can read this content</info>
</notes></content>
</root>
And finally modify the query to run in the context of els-user-3:
// run this query against the Documents database
xdmp.eval("fn.doc('attributes.xml')", null,
{
"userId" : xdmp.user("els-user-3")
});
=>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Document Title</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<info attr="EU">Only role with "EU" attribute can read this summary</info>
<info attr="UK">Only role with "UK" attribute can read this summary</info>
</executive-summary>
<content>Contents of document
Unclassified content
<notes>
<info attr="EU">Only role with "EU" attribute can read this content</info>
<info attr="UK">Only role with "UK" attribute can read this content</info>
</notes></content>
</root>
The els-user-3 has protected path permissions on both elements with the “EU” info attribute and the elements with the “UK” info attribute. This way, the user can see both elements.
Note: If you run the query in the context of the admin user, you will be able to see the entire document because the query is using fn.doc().