Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 227
  • Last Modified:

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
0
idesta
Asked:
idesta
  • 9
  • 5
1 Solution
 
Geert BormansCommented:
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!
0
 
Geert BormansCommented:
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
0
 
idestaAuthor Commented:
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
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Geert BormansCommented:
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
0
 
idestaAuthor Commented:
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.














0
 
idestaAuthor Commented:
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
0
 
idestaAuthor Commented:
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
0
 
idestaAuthor Commented:
I would be happy to spilt this into several questions if needs be.
0
 
idestaAuthor Commented:
count(//Call/ObjectSurveys/ObjectSurvey/Results/Result[not(Reference = preceding::Result/Reference)]) always returns 1?
0
 
idestaAuthor Commented:
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... :)
0
 
Geert BormansCommented:
idesta,

maybe this can help you.
I created a frame XML, which I hope comes close to your source

<?xml version="1.0" encoding="UTF-8"?>
<Call>
<ObjectSurveys>
    <ObjectSurvey>
        <Results>
            <Result>
                <Reference>AAEDABJ180</Reference>
            </Result>
            <Result>
                <Reference>AAEDABJ179</Reference>
            </Result>
            <Result>
                <Reference>AAEDABJ180</Reference>
            </Result>
            <Result>
                <Reference>AAEDABJ179</Reference>
            </Result>
            <Result>
                <Reference>AAEDABJ180</Reference>
            </Result>
            <Result>
                <Reference>AAEDABJ181</Reference>
            </Result>
        </Results>
    </ObjectSurvey>
</ObjectSurveys>
</Call>

Here is how to do key grouping with this XML

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:key name="ref-to-res" match="Result" use="Reference"/>
   
    <xsl:template match="Results">
        <xsl:for-each select="Result[generate-id() = generate-id(key('ref-to-res', Reference)[1])]">
            <xsl:value-of select="Reference" />
            <xsl:text> </xsl:text>
            <xsl:value-of select="count(key('ref-to-res', Reference))"/>
            <xsl:text> </xsl:text>
            <xsl:for-each select="key('ref-to-res', Reference)">
                <!-- do something usefull with the loop -->
            </xsl:for-each>
        </xsl:for-each>
     </xsl:template>
   
</xsl:stylesheet>

here is an article on Muenchian grouping that explains this very clearly
http://www.jenitennison.com/xslt/grouping/muenchian.xml

cheers
0
 
idestaAuthor Commented:
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
0
 
Geert BormansCommented:
welcome,
if you need help to close the final gaps, don't hesitate to ask
cheers
0
 
idestaAuthor Commented:
ok then, I asked but Im offering the points:

http://www.experts-exchange.com/Web/Web_Languages/XML/Q_21881296.html
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 9
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now