I have the following xml
<smses>
<sms address="87654321" type="1" body="Some text" readable_date="3/09/2011 2:16:52 PM" contact_name="Person1" />
<sms address="87654321" type="2" body="Some text" readable_date="3/09/2011 2:36:41 PM" contact_name="Person1" />
<sms address="87654321" type="1" body="Some text" readable_date="3/09/2011 2:16:52 PM" contact_name="Person1" />
<sms address="123" type="2" body="Some text" readable_date="3/09/2011 10:56:24 AM" contact_name="Person2" />
<sms address="123" type="1" body="Some text" readable_date="3/09/2011 10:57:52 AM" contact_name="Person2" />
<sms address="123" type="2" body="Some text" readable_date="3/09/2011 10:56:24 AM" contact_name="Person2" />
<sms address="12345678" type="1" body="Some text" readable_date="3/09/2011 11:21:16 AM" contact_name="Person3" />
<sms address="12345678" type="2" body="Some text" readable_date="3/09/2011 11:37:21 AM" contact_name="Person3" />
<sms address="12345" type="2" body="Some text" readable_date="28/01/2011 7:24:50 PM" contact_name="(Unknown)" />
<sms address="233" type="1" body="Some text" readable_date="30/12/2010 1:13:41 PM" contact_name="(Unknown)" />
</smses>
I am trying to get an ouput like this (e.g. xml)
<sms contact_name="person1">
<message type="1">{@body}</message>
<message type="2">{@body}</message>
<message type="1">{@body}</message>
</sms>
<sms contact_name="person2">
<message type="2">{@body}</message>
<message type="1">{@body}</message>
</sms>
<sms contact_name="person3">
<message type="2">{@body}</message>
<message type="1">{@body}</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">{@body}</message>
<message type="1">{@body}</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">{@body}</message>
</sms>
e.g. html
<div>
<h1>Person: @contact_name (@address)</h1>
<p>message @type: @body</p>
</div>
I have managed to do this with the following XSLT code (please excuse the code below does not reflect the html entirely, the output is the desired result!)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="txt" match="sms" use="@contact_name" />
<xsl:template match="smses">
<xsl:apply-templates select="sms[generate-id(.)=generate-id(key('txt', @contact_name)[1])]">
<xsl:sort select="@address" order="ascending" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="sms">
<h4><xsl:value-of select="@contact_name" /></h4>
<xsl:for-each select="key('txt', @contact_name)">
<br />
<xsl:value-of select="@body" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The problem I have is, or rather the question I'm asking. I have a sms element with a @contact_name
attribute that is "(unknown)" but the @address
is unique between both elements, i.e. they should not be grouped together, because the sms message came from a different number/person (even though the contact name is the same, its irrelevant).
Should I be trying to reorder/change the XML data or is there a way to get XSLT to recognise the group for unknown should check if the @address
is different if the @contact_name
is the same.
Edit:
I failed to mention (or rather forgot) that while there are some sms messages with same @contact_name
and unique @address
there is also cases where some of the @address
fields have slight discrepancy where they don't have the country code in front of the number, e.g.
<sms contact_name="jared" address="12345" />
<sms contact_name="jared" address="+64112345" />
But they are meant to be grouped because they are from the same person/number.
Edit:
In my situation there would only be discrepancies of having 3 character (e.g. +64) country code plus 2 digit network code (e.g. 21). Basically the outcome should be, if @contact_name
= same and @address
is completely different
i.e.
<sms contact_name="jared" address="12345" />
<sms contact_name="jared" address="5433467" />
then they should be seperate elements, as they are from different people/number(s).
if @contact_name
= same and @address
is different only by country and network codes
i.e.
<sms contact_name="jared" address="02112345" />
<sms contact_name="jared" address="+642112345" />
then they should be grouped as they are from the same person/number
Edit:
country codes: +64 (3 characters)
network codes: 021 (3 characters, usually last character changes depending on network)
Numbers (@address
) get saved per <sms>
either as +64-21-12345 (excluding dashes) or 021-12345(excluding dash).