IBM webMethods Hybrid Integration

IBM webMethods Hybrid Integration

Join this online group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only

Sibling Axis workaround: getting to nodes before and behind

  • 1.  Sibling Axis workaround: getting to nodes before and behind

    Posted Fri November 23, 2007 02:50 PM

    Hi,
    I thought I’d provide a sample solution to a problem I have had since 2002 but which at a new attempt I was able to solve using Tamino 4.4.1.

    The problem: I needed to access an interval around a node, that is n sibling nodes before and m sibling nodes behind a node. And the node itself would be nice as well. Take something like

    <paragraph> 
    <word>Sample</word> 
    <word>for</word> 
    <word>a</word> 
    <word>context</word> 
    <word>based</word> 
    <word>search</word> 
    <word>like</word> 
    <word>a</word> 
    <word>concordance</word> 
    </paragraph> 

    I want to have something like two nodes before “search” and one behind, the result should be in the same structure but without all the other words. In fact this is meant to be used as a concordance. Previous attempts were problematic, but here is the solution that works. Not pretty, but it does what it is supposed to do. I thought this kind of query could be of some interest to others, so I post it here without accepting any liabilities :slight_smile: If someone has a prettier or more elegant version, feel free to post it.

    There is some redundancy left in for debugging purposes. The construct for the upper limit restricts the maximum number of iterations, just to be on the safe side, if a bug is included then this really safes a lot of waiting time.
    BTW you might need to remove the comments, at least the Interactive Interface does not like them, though my debugger does not complain.

     
    (:  These are the context functions, requiring the number of words before and behind, the context, a counter and an upper limit :) 
    
    declare function local:leftcontext($searchword as element(), $counter, $upperlimit, $wordsbefore) as element()* 
    { 
    for $context in $searchword/.. 
    return   
    if ($context/word[$counter] = $searchword) 
    then  
    <leftcontext> 
    {      $context/word[position() < $counter and position()> $counter - $wordsbefore -1 ] } 
    </leftcontext> 
    else  
    if ($counter<=$upperlimit)  
    then       local:leftcontext($searchword, $counter + 1, $upperlimit, $wordsbefore) 
    else <debug>{$counter},  {$upperlimit}, {$searchword},  
    <context>{$context}</context></debug> 
    }; 
    
    declare function local:rightcontext($searchword as element(), $counter, $upperlimit,  $wordsbehind) as element()* 
    { 
    for $context in $searchword/.. 
    return   
    if ($context/word[$counter] = $searchword) 
    then  
    <rightcontext> 
    {      $context/word[position()  > $counter and position() < $counter + $wordsbehind +1] } 
    </rightcontext> 
    else  
    if ($counter<=$upperlimit)  
    then local:rightcontext($searchword, $counter + 1, $upperlimit,  $wordsbehind) 
    else <debug>{$counter},  {$upperlimit}, {$searchword},  
    <context>{$context}</context></debug> 
    }; 
    
    (: This function provides the information necessary for a counter and  
    concatenates the right and left contexts with the searchword in between  :) 
    
    declare function local:countcontext($searchword as element(), $wordsbefore , $wordsbehind) as element()* 
    {  
    for $context in $searchword/.. 
    let $positions := count($context/word) ,  
    $counterinitial := 1 
    return  
    <paragraph> 
    { 
    local:leftcontext($searchword , $counterinitial , $positions, $wordsbefore )  
    } 
    <searchword>{$searchword/text()}</searchword>  
    { 
    local:rightcontext($searchword , $counterinitial , $positions, $wordsbehind ) 
    } 
    </paragraph> 
    }; 
    
    (: The real function :) 
    
    for $searchword in collection("SAMPLECOLLECTION")//paragraph 
    let $wordsbefore := 2, 
    $wordsbehind := 1, 
    $searchwordstring := "search" 
    where $searchword/text()= $searchwordstring 
    return local:countcontext($searchword, $wordsbefore, $wordsbehind ) 

    May it be useful for somebody else…


    #webMethods
    #Tamino
    #API-Management