XPATH query to retrieve documents from different root folders

Hi guys,

We have a document type (Articles) that contains a multi-value property of which is another document type (Categories). These document types are in multiple languages with each language having it’s own root folder.

Articles of one language should only contain categories from that of it’s own language. We are trying to create an XPath query to return all articles that contain at least one Category of a different root folder (e.g. en/US Article containing an en/CA Category) .

Since our system contains a large number of Articles we are trying to avoid looking trough every Category within every Article individually, whilst trying to make this as quick as possible and XPath query seems to be the best option.

We have tried multiple queries similar to the following but have had no luck preventing Articles that solely contain Categories from the en/US folder from being returned:

/jcr:root/content/documents/en/US//element(*,EAP:Article)[@EAP:categories/hippo:docbase!='5455b164-b7fa-4cc9-b180-bfdd3d71ccf7' and @EAP:categories/hippo:docbase!='8ec09a26-15a0-49ac-8dfc-33a8999fd247' and @EAP:categories/hippo:docbase!='6b4e3185-d50d-440f-af12-fae4cc0f2b47' and @EAP:categories/hippo:docbase!='3f7b6359-5d6c-4a0d-a091-1d84f73775b4' and @EAP:categories/hippo:docbase!='cafebabe-cafe-babe-cafe-babecafebabe']

Thank you in advance for your time,
Razvan Adam

If you don’t have too many Canadian category documents perhaps you can do [@EAP:categories/hippo:docbase = ‘uuid1’ or @EAP:categories/hippo:docbase!=‘uuid2’ where uuid1 and uuid2 are the handle uuids or the Canadian ones of course.

Otherwise maybe prevent earlier to not select Canadian categories from US articles?

We did not manage to do it via XPath query so instead we did it programatically.

Hi tausif,

To achieve this pragmatically we had to run 2 queries on our code

  • First query was to get Document Type based on a Document Property.

  • Second query was to get list of documents to check for incorrect language property.

The results of the second query were stored in a Set list of Strings to ensure there were no duplicates.

Bellow is the code used:

    String path = params.getPath();
    String rootPath = "/jcr:root" + (path.startsWith("/")?"":"/") + path;
    String element = "//element(*,%s)";
    IProperty property;

    if(params.getProject().equalsIgnoreCase("WELL")) {
    	property = params.getWELLPropertyEnum();
    } else {
    	property = params.getEAPPropertyEnum();

    Query typeQuery = queryManager.createQuery(rootPath + String.format(element, property.getNodeType()), Query.XPATH);
    LOG.debug("Query to get Document Type based on a Document Property: " + typeQuery);

    ArrayList<String> propertyIds = new ArrayList<String>();
    QueryResult result = typeQuery.execute();
    NodeIterator nodeIter = result.getNodes();

    while(nodeIter.hasNext()) {
    	Node node = nodeIter.nextNode();
    	HippoDocument document = (HippoDocument) wpm.getObject(node.getPath());

    if(!property.isRequired()) {

    String checkQuery;

    if(params.getRootNode() != null) {
    	checkQuery = rootPath + String.format(element, params.getRootNode());
    } else {
    	checkQuery = rootPath + String.format(element, property.getSuperNodeType());

    LOG.debug("Query to get list of documents to check for incorrect language property: " + checkQuery);
    Query docQuery = queryManager.createQuery(checkQuery, Query.XPATH);

    Set<String> paths = getInconsistentProperties(wpm, property, propertyIds, docQuery);

    return paths;

Hi Razvan, thank you for the response. I did it slightly differently since the path from where I need to fetch the document was fixed. This is what I did:

// get the resource bundle node
Node node = context.getSession()

// get the Hippo document
HippoDocument document = (HippoDocument) context.getObjectConverter().getObject(node);

// collect the keys and values in a Map
Value[] keys = document.getNode().getProperty(PROP_KEYS).getValues();
Value[] values = document.getNode().getProperty(PROP_MESSAGES).getValues();

Map<String, String> bundle = new HashMap<String, String>();
for (int i = 0; i < keys.length; i++) {
	bundle.put(keys[i].getString(), values[i].getString());