Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Xml sorting with XSL

Status
Not open for further replies.

FabricioItaly

Technical User
Nov 29, 2007
2
0
0
IT
Hi everybody
Hope someone can help me.

I have to sort the output for this xml file
Code:
<?xml version='1.0' encoding='ISO-8859-1' standalone='no' ?>
<ricerca>
 <documento dnome='doc1'>
    <tag tname='t1'>
       <match>1</match>
    </tag>
    <tag tname='t2'>
       <match>1</match>
    </tag>
     <tag tname='t3'>
       <match>1</match>
    </tag>
</documento>
<documento dnome='doc2'>
    <tag tname='t1'>
       <match>0</match>
    </tag>
    <tag tname='t2'>
       <match>1</match>
    </tag>
         <tag tname='t3'>
       <match>0</match>
    </tag>
</documento>
<documento dnome='doc3'>
    <tag tname='t1'>
       <match>1</match>
    </tag>
    <tag tname='t2'>
       <match>0</match>
    </tag>
    <tag tname='t3'>
       <match>1</match>
    </tag>
</documento>
 <documento dnome='doc4'>
    <tag tname='t1'>
       <match>0</match>
    </tag>
    <tag tname='t2'>
       <match>0</match>
    </tag>
     <tag tname='t3'>
       <match>0</match>
    </tag>
</documento>
 <documento dnome='doc5'>
    <tag tname='t1'>
       <match>1</match>
    </tag>
    <tag tname='t2'>
       <match>1</match>
    </tag>
     <tag tname='t3'>
       <match>0</match>
    </tag>
</documento>
 <documento dnome='doc6'>
    <tag tname='t1'>
       <match>0</match>
    </tag>
    <tag tname='t2'>
       <match>0</match>
    </tag>
     <tag tname='t3'>
       <match>1</match>
    </tag>
</documento>
 <documento dnome='doc7'>
    <tag tname='t1'>
       <match>1</match>
    </tag>
    <tag tname='t2'>
       <match>1</match>
    </tag>
     <tag tname='t3'>
       <match>1</match>
    </tag>
</documento>
</ricerca>
this xml is built run-time, so the numbers of the documents and the tags can be different.

I made a simple xsl:
Code:
<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
<xsl:output method="html"/>
  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates select="ricerca/documento"/>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="documento">
    <h1>
      <xsl:value-of select="."/>
      <xsl:value-of select="@dnome"/>
    </h1>
  </xsl:template>
</xsl:stylesheet>

which make this output.
Code:
1 1 1 doc1
0 1 0 doc2
1 0 1 doc3
0 0 0 doc4
1 1 0 doc5
0 0 1 doc6
1 1 1 doc7


but I want my output is:
Code:
0 1 0 doc2
1 1 0 doc5
1 1 1 doc1
1 1 1 doc7
1 0 1 doc3
0 0 1 doc6
- documents with more occurences tag=1 printed in the middle of the page
-documents with more occurences tag=0 printed in the top and in the bottom of the page
-documente with all tag=0 not printed

someone can help me??
Thanks
 
>- documents with more occurences tag=1 printed in the middle of the page
>-documents with more occurences tag=0 printed in the top and in the bottom of the page
>-documente with all tag=0 not printed
This kind of description as spec is way off the acceptable standard of clarity and well-definedness. You must make a sense out of what you want yourself first.

There are many ways to look at the examples. One that is sure is linear weight as order-parameter is excluded (Can you see what I mean? do some arithmetic!) So to safe myself some mind-guessing, this is what I conclude:
[tt]
- t1 use match document order
- t2 use match descending order
- t3 use match ascending order
- some of matches with in document : non-zero[/tt]

This is by no mean unique, mind you?
[tt]
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="ricerca"/>
</body>
</html>
</xsl:template>

<xsl:template match="ricerca">
<h1>
<xsl:for-each select="documento[not(sum(.//tag/match/text()) = 0)]">
<!-- my reading is "match" for t1:document order; for t2: descending; for t3: accending -->
<xsl:sort select="tag[@tname='t2']/match" order="descending" />
<xsl:sort select="tag[@tname='t3']/match" order="ascending" />
<xsl:value-of select="."/>
<xsl:value-of select="@dnome"/>
<br />
</xsl:for-each>
</h1>
</xsl:template>
[/tt]
 
Further note:
Forgotten to mention clearly that the sort order is taking t2 as primary and t3 as secondary (also reflected in the template).
 
Hi
at first: thanks so much, sorry but my english is bad, so i find difficult to explain what i want...

anyway
the output order is what you gave me
but


the "tag" number is run-time generated, so while i'm coding i can't know the number and the names of the 'tag's (but inside every document tag names and number are the same )
So i can have a file like this:
xml
Code:
......
 <documento dnome='doc5'>
    <tag tname='t1'>
       <match>1</match>
    </tag>
    <tag tname='t2'>
       <match>1</match>
    </tag>
</documento>
 <documento dnome='doc6'>
    <tag tname='t1'>
       <match>1</match>
    </tag>
    <tag tname='t2'>
       <match>0</match>
    </tag>
</documento>
.......
or a file like this...
xml
Code:
......
 <documento dnome='doc5'>
    <tag tname='xxx'>
       <match>1</match>
    </tag>
    <tag tname='yyy'>
       <match>1</match>
    </tag>
     <tag tname='zzz'>
       <match>0</match>
    </tag>
</documento>
 <documento dnome='doc6'>
    <tag tname='xxx'>
       <match>0</match>
    </tag>
    <tag tname='yyy'>
       <match>0</match>
    </tag>
     <tag tname='zzz'>
       <match>1</match>
    </tag>
</documento>
....


and also i would like to show the order like (just an exemple)
Code:
0 1 0 doc2 (font size 8)
1 0 1 doc3 (font size 10)
1 1 1 doc1 (font size 14)
1 1 1 doc7 (font size 14)
1 1 0 doc5 (font size 10)
0 0 1 doc6 (font size 8)
(and i'd like tu put the document name and the tag/match number in a table..)
how i can do?


thanks

Fabrizio
 
[1] In you re-cap using t1, t2..., why you left out t3? I hope that's just a miss-out and you meant there are all the same have three child "tag" elements.

[2] I assume [1]. Under the assumption that the tname is getting all the freedom - that is a curious kind of freedom you grant there if you allow even one set under documento xxx,yyy,zzz and the other set aaa,bbb,ccc - but what follows is not depending on that only allowing that - you can use position as the signature. Hence you can replace the predicat using position.
[tt]
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="ricerca"/>
</body>
</html>
</xsl:template>

<xsl:template match="ricerca">
<h1>
<xsl:for-each select="documento[not(sum(.//tag/match/text()) = 0)]">
<!-- my reading is "match" for t1:document order; for t2: descending; for t3: accending -->
<xsl:sort select="tag[position() = 2]/match" order="descending" />
<xsl:sort select="tag[position() = 3]/match" order="ascending" />
<xsl:value-of select="."/>
<xsl:value-of select="@dnome"/>
<br />
</xsl:for-each>
</h1>
</xsl:template>
[/tt]
[2.1] There is a shortcut to it by omitting position(), like this. But I've used the fully explicit version above.
[tt]
<xsl:sort select="tag[2]/match" order="descending" />
<xsl:sort select="tag[3]/match" order="ascending" />
[/tt]
[2.2] You can add another attribute data-type to the xsl:sort element if there is a possibility of doubt. Since there isn't, I have omitted it.
[tt] data-type="number"[/tt]

[3] As to the "font size ..." I have no idea where it comes from. If you know, you just add it as text together with the doc<n>.

[4] If you want to put thing on a table, you have to do it yourself as it is no new independent and generic difficulty from the perspective of xsl associated with it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top