Link to home
Start Free TrialLog in
Avatar of idesta
idesta

asked on

Group together nodes that have similar content. then return count of uniques.

Hi I am trying to create an incrementing positive integer value.
I will use this to logically sort information/data when it is presented to the client.

The values I want to parse are stored in the 'Reference' field of my XML data - Xpath attached.

/Call/ObjectSurveys/ObjectSurvey/Results/Result[Reference]


I will get like 4 results with a reference of AAEDABJ179
then 6 with AAEDABJ180
then 2 with AAEDABJ181

etc etc...

what I need is to COUNT how many unique references there are in total (in the above example there would be 3)
RETURN THIS TOTAL VALUE and the constituant references as a pair

like
1=AAEDABJ179
2=AAEDABJ180
3=AAEDABJ181

ideally I would like to be able to step through the results afterward like:

<script language="javascript1.1" type="text/javascript">
<![CDATA[
 function ReplaceContent(sNodeName, sContent)
{
   var i = 1;    var oNode;   var aNodes = document.getElementById(sNodeName);

     while ( oNode = document.getElementById(sNodeName ) )
            {
             oNode.innerHTML = sContent;
             oNode.id = oNode.id+'converted';
             i++;
             }
}  
]]>
</script>

<xsl:for-each select="$er">    <!- where $er is cleverly doing something useful ! //-->
           <xsl:if test="string-length(../Text) &gt; 0">
            ReplaceContent("<xsl:value-of select="ExternalRef"/>","<xsl:value-of select="$er"/>");
            </xsl:if>
</xsl:for-each>





then use the 'n' value as incrementally increasing integer value (between 1 and say 10)

<div id="page(n)" style="padding:0px;overflow:hidden;display:block;">
<div style="position: absolute; top: 155px; right: 80px; left: 114px; width: 250px; height: 20px;" class="page(n)" id="SiteName">------ </div></div>

and setup 1 PAGE div for each of my unique refrences...

thanks in advance... if this need clarification then gimme a nudge, thanks
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Hi idesta,
> /Call/ObjectSurveys/ObjectSurvey/Results/Result[Reference]

if you change your XPath like this
/Call/ObjectSurveys/ObjectSurvey/Results/Result[not(Reference = preceding::Result/Reference)]
you will only get the Result elements that have a unique Reference
(always the first one is selected)

Cheers!
idesta,

to get the number of unique entries, you just need to count them
count(//Call/ObjectSurveys/ObjectSurvey/Results/Result[not(Reference = preceding::Result/Reference)])

if you want to iterate over them in a DOM structure, use selectNodes

var aNodes = document.selectNodes("//Call/ObjectSurveys/ObjectSurvey/Results/Result[not(Reference = preceding::Result/Reference)]/Reference");

cheers
Avatar of idesta
idesta

ASKER

Hi Gertone.

I will give that a try.
I thought I might have to use keys?
Thanks G., Ill get back to you ;)

Idesta Si
Keys is another option,
it might turn out faster
this one is pure XPath and comes in handy when you just want to select unique nodes
cheers
Avatar of idesta

ASKER

I have over a thousand nodes to iterate on.
I would expect to do around a thousand iterations a day however so this is not life threatening, but I have to put this on a productions server.
So far in this project the thinking has been trying to push all the cpu-hungry load server side with post processing DOM nodes using the javascript functions invoked from the client-side browser - the function I demonstrated above, I am unsure of the advisedness of this in retrospect, but the work is done.

Simply, In short: All I am trying to do is group some 'result'.text nodes together. So I can show and hide the groups of divs in a browser by clicking somewhere... you get the idea.
I'll handle the hiding and showing etc... But I need the groups returning

In Long: The output I am parsing has a load of redundant structure around the results I need. The structure wraps results attached to groups of the original questions and these questions are wrapped in a tag of type 'surveys' all indentified together however by the value 'reference'. Would this affect my choice of Keys or your method? I think so? the \\ instruction would be very server heavy I believe, but I am not well informed.

All of this aside...

the important bits are: <xsl:for-each select="$er"> where I define the sets of data I am returning...

should this be a:      <xsl:for-each select="$er"> <!-- where this is the array of groups returned when sorting by reference
and then:                <xsl:for-each select="$er">  <!-- Individual structures within each group.

</
</

or am I completely missing how simple it should be to tag up:

<div id="page(n)" style="padding:0px;overflow:hidden;display:block;">
<div style="position: absolute; top: 155px; right: 80px; left: 114px; width: 250px; height: 20px;" class="page(n)" id="SiteName">------ </div></div>

where each (n) is the index of the groups returned and dynamically print that excerpt above (n) number of times into the resulting file.

I hope it is just really easy and Im being thick, because I dont get it.
Thanks.














Avatar of idesta

ASKER

sorry the point of all that was:

var aNodes = document.selectNodes("//Call/ObjectSurveys/ObjectSurvey/Results/Result[not(Reference = preceding::Result/Reference)]/Reference");

I am unsure how to use this? I suspect I cant basically.
thanks
Avatar of idesta

ASKER

Please could you explain how to do the same thing with keys?
I need the data returning in groups defined by the refrence rather than the 1st node.
I with to iterate through the resulting data set.

Many thanks.
Simon
Avatar of idesta

ASKER

I would be happy to spilt this into several questions if needs be.
Avatar of idesta

ASKER

count(//Call/ObjectSurveys/ObjectSurvey/Results/Result[not(Reference = preceding::Result/Reference)]) always returns 1?
Avatar of idesta

ASKER

is this the right direction?

      <xsl:key name="pages" match="/Call/ObjectSurveys/ObjectSurvey/Results/Result[Reference]" use="/Call/ObjectSurveys/ObjectSurvey/Results/Result[not(Reference = preceding::Result/Reference)]/Reference"/>

<xsl:template match="pages">
<xsl:apply-templates
      select="*[Reference and
                generate-id(.)=generate-id(key('pages', Reference))]" />
</xsl:template>


<xsl:template match="*[./Reference]">
      <!-- first column is the value of the partNum attribute -->
  <xsl:value-of select="./Reference" />
    <!-- second column is the number of parts with that partNum -->
<xsl:value-of select="count(key('pages', ./Reference))" />
 
</xsl:template>


<xsl:template match="/">

<xsl:for-each select="/Call/ObjectSurveys/ObjectSurvey/Results/Result">
<xsl:for-each select=".[not(Reference = preceding::Result/Reference)]/Reference">
<xsl:value-of select="position()"/>
<xsl:value-of select="../Text"/>
<![CDATA[
]]>
</xsl:for-each>
</xsl:for-each>
</xsl:template>      



thanks... I am trying... :)
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of idesta

ASKER

TBH.
This doesnt answer my question, but my question was so poorly defined that it is a miracle you got me anywhere close. which incidentally I now am.

Excellent work G.

good luck with the 'Sage' level - have 500 points
welcome,
if you need help to close the final gaps, don't hesitate to ask
cheers