private String generateSimpleConstraints ( Node node , boolean isRoot ) { //Index of child node int childElementIndex = 0 ; final StringBuilder out = new StringBuilder ( ) ; boolean queryHasText = false ; final NonWhitespaceNodeList nodeList = new NonWhitespaceNodeList ( node . getChildNodes ( ) ) ; for ( final Node child : nodeList ) { if ( child . getNodeType ( ) == Node . ELEMENT_NODE ) { //If an element node and not an attribute or text node, add to xquery and increment index childElementIndex ++ ; boolean wasSpecialElement = handleSpecialElements ( child , childElementIndex ) ; if ( wasSpecialElement ) { continue ; // this was a special element and was handled otherwise (e.g. qvar) } // We only want to consider elements below the content mathml semantics, // a deeper lying annotation-node should be ignored boolean annotationNode = child . getLocalName ( ) != null && XMLHelper . ANNOTATION_XML_PATTERN . matcher ( child . getLocalName ( ) ) . matches ( ) ; if ( ! annotationNode ) { if ( queryHasText ) { //Add another condition on top of existing condition in query out . append ( " and " ) ; } else { queryHasText = true ; } //The first direct child of the root element is added as a constraint in getString() //so ignore it here if ( ! isRoot ) { //Add constraint for current child element out . append ( "*[" ) . append ( childElementIndex ) . append ( "]/name() = '" ) . append ( child . getLocalName ( ) ) . append ( "'" ) ; } if ( child . hasChildNodes ( ) ) { if ( ! isRoot ) { setRelativeXPath ( getRelativeXPath ( ) + "/*[" + childElementIndex + "]" ) ; //Add relative constraint so this can be recursively called out . append ( " and *[" ) . append ( childElementIndex ) . append ( "]" ) ; } final String constraint = generateSimpleConstraints ( child ) ; if ( ! constraint . isEmpty ( ) ) { //This constraint appears as a child of the relative constraint above (e.g. [*1][constraint]) out . append ( "[" ) . append ( constraint ) . append ( "]" ) ; } } } } else if ( child . getNodeType ( ) == Node . TEXT_NODE ) { //Text nodes are always leaf nodes out . append ( "./text() = '" ) . append ( child . getNodeValue ( ) . trim ( ) ) . append ( "'" ) ; } } //for child : nodelist if ( ! isRoot && isRestrictLength ( ) ) { // Initialize constraint or add as additional constraint setLengthConstraint ( ( getLengthConstraint ( ) . isEmpty ( ) ? "" : getLengthConstraint ( ) + "\n and " ) + "fn:count($x" + getRelativeXPath ( ) + "/*) = " + childElementIndex ) ; } if ( ! getRelativeXPath ( ) . isEmpty ( ) ) { String tmpRelativeXPath = getRelativeXPath ( ) . substring ( 0 , getRelativeXPath ( ) . lastIndexOf ( "/" ) ) ; setRelativeXPath ( tmpRelativeXPath ) ; } return out . toString ( ) ; }
Generates qvar map length constraint and returns exact match XQuery query for all child nodes of the given node . Called recursively to generate the query for the entire query document .