0

I'm using XPATH 1.0 parsers alongside CLiXML in my JAVA project, I'm trying to setup a CLiXML constraint rules file.

I would like to show an error if there are duplicate element names under a specific child.

For example

<parentNode version="1">
    <childA version="1">
        <ignoredChild/>
    </childA>
    <childB version="1">
        <ignoredChild/>
    </childB>
    <childC version="4">
        <ignoredChild/>
    </childC>
    <childA version="2">
        <ignoredChild/>
    </childA>
    <childD version="6">
        <ignoredChild/>
    </childD>
</parentNode>

childA appears more than once, so I would show an error about this.

NOTE: I only want to 'check/count' the Element name, not the attributes inside or the children of the element.

The code inside my .clx rules file that I've tried is:

<forall var="elem1" in=".//parentNode/*">
    <equal op1="count(.//parentNode/$elem1)" op2="1"/>
</forall>

But that doesn't work, I get the error:

Caused by: class org.jaxen.saxpath.XPathSyntaxException: count(.//PLC-Mapping/*/$classCount: 23: Expected one of '.', '..', '@', '*', <QName>

As I want the code to check each child name and run another xPath query with the name of the child name - if the count is above 1 then it should give an error.

Any ideas?

dan2k3k4
  • 1,388
  • 2
  • 23
  • 48

2 Answers2

1

Just try to get list of subnodes with appropriate path expression and check for duplicates in that list:

   XPathExpression xPathExpression = xPath.compile("//parentNode/*");
   NodeList children = (NodeList) xPathExpression.evaluate(config, XPathConstants.NODESET);

   for (int i = 0; i < children.getLength(); i++) {
   // maintain hashset of clients here and check if element is already there
   }
Victor Sorokin
  • 11,878
  • 2
  • 35
  • 51
  • I've updated my question, realised I wasn't that clear. I don't want to perform the custom 'constraint' check in Java, I want to set it up in my .CLX file. – dan2k3k4 Jul 06 '11 at 14:12
  • @Dan2k3k4 Sorry, don't have explicit XPath expression which gives yes/no answer immediately. – Victor Sorokin Jul 06 '11 at 14:16
1

This cannot be done with a single XPath 1.0 expression (see this similar question I answered today).

Here is a single XPath 2.0 expression (in case you can use XPath 2.0):

/*/*[(for $n in name() 
      return count(/*/*[name()=$n]) 
      )
     >1
     ]

This selects all elements that are children of the top element of the XML document and that occur more than once.

Community
  • 1
  • 1
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431