Re: select nodes with xpath, having by specific attribute named 'class' the 'subvalue part' set

Martin Honnen <[email protected]>
Newsgroups gmane.comp.mozilla.devel.xml
Organization Liberty Development
Message-ID <[email protected]>

Marek Mänd wrote:

> <style>
>   .marek{}
> </style>
> etc..
> <root>
> <element class="marek mand"/>
> <element class="mand marek"/>
> <element class="mand marekmänd"/>
> <element class="mand marekk"/>
> </root>
> 
> I would like to know what is the XPath expression for Mozillas 
> JavaScript document.evaluate method first argument, if i want to get all 
> the nodes, that have the 'css'-class named "marek" set.
> 
> By above data only 2 elements should be returned, because they and they 
> only have the 'css' class "marek" set. The XPath expression should not 
> match 'marekk' nor 'marekmänd'.

XPath 1.0 is not very strong in dealing with string values which are 
really a list of separate values thus if you are using XPath within 
JavaScript I think it is easier to start with XPath e.g.
   //element[contains(@class, 'marek')]
and then look at the result and use a JavaScript regular expression on 
the class attribute value to find those that match what you are looking for:

   function findElementsByClassName (xmlDocument, className) {
     var classNamePattern = new RegExp('(^|\\s+)' + className + '(\\s+|$)');
     var xpathExpression = '//*[contains(@class, "' + className + '")]';
     var elements = [];
     var xpathResult = xmlDocument.evaluate(
       xpathExpression,
       xmlDocument,
       null,
       XPathResult.ORDERED_NODE_ITERATOR_TYPE,
       null
     );
     var element;
     while ((element = xpathResult.iterateNext())) {
       classNamePattern.lastIndex = 0;
       if (classNamePattern.test(element.getAttribute('class'))) {
         elements.push(element);
       }
     }
     return elements;
   }

Using only XPath 1.0 it is very convoluted, watch out for line breaks 
the posting introduces:

   function findElementsByClassName (xmlDocument, className) {
     var xpathExpression =
'//element[normalize-space(@class) = "' + className + '"' +
' or starts-with(normalize-space(@class), "' + className + ' ")' +
' or contains(normalize-space(@class), " ' + className + ' ")' +
' or (substring(normalize-space(@class), 
string-length(normalize-space(@class)) ' +
' - string-length(" ' + className + '") + 1) = " ' + className + '")]';
     var elements = [];
     var xpathResult = xmlDocument.evaluate(
       xpathExpression,
       xmlDocument,
       null,
       XPathResult.ORDERED_NODE_ITERATOR_TYPE,
       null
     );
     var element;
     while ((element = xpathResult.iterateNext())) {
       elements.push(element);
     }
     return elements;
   }


-- 

	Martin Honnen
	http://JavaScript.FAQTs.com/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.