使用xslt从xml按多个属性分组
我有以下xml使用xslt从xml按多个属性分组,xml,xslt,xslt-1.0,Xml,Xslt,Xslt 1.0,我有以下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="P
<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>
但是,它们应该分组,因为它们来自同一个人/号码
编辑:
在我的情况下,只有3个字符(例如+64)的国家代码加上2位数的网络代码(例如21)才会出现差异。基本上,如果@contact\u name
=相同且@address
完全不同,结果应该是
i、 e
然后,他们应该分组,因为他们来自同一个人/号码
编辑:
国家代码:+64(3个字符)
网络代码:021(3个字符,通常最后一个字符根据网络而变化)
数字(
@address
)将根据
保存为+64-21-12345(不包括破折号)或021-12345(不包括破折号)。此转换使用带复合键的明钦分组:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kContactByNameAddress" match="sms"
use="concat(@contact_name,'+',@address)"/>
<xsl:template match=
"sms[generate-id()
=
generate-id(key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)
[1]
)
]
">
<sms contact_name="{@contact_name}">
<xsl:apply-templates mode="inGroup"
select="key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)"/>
</sms>
</xsl:template>
<xsl:template match="sms" mode="inGroup">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
<xsl:template match="sms"/>
</xsl:stylesheet>
<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>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
concat(substring($string1, 1 div $condition),
substring($string2, 1 div not($condition))
)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:for-each-group select="sms" group-by=
"concat(@contact_name,'+',
if(starts-with(@address,'+'))
then substring(@address, 4)
else @address
)">
<sms contact_name="{@contact_name}">
<xsl:apply-templates select="current-group()"/>
</sms>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="sms">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
</xsl:stylesheet>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
将此转换应用于以下XML文档时(根据新发布的规则,前一个+添加了三个sms
元素,其中两个元素具有“相同”的地址):
以下XPath表达式在计算时与上述表达式等效:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kContactByNameAddress" match="sms"
use="concat(@contact_name,'+',@address)"/>
<xsl:template match=
"sms[generate-id()
=
generate-id(key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)
[1]
)
]
">
<sms contact_name="{@contact_name}">
<xsl:apply-templates mode="inGroup"
select="key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)"/>
</sms>
</xsl:template>
<xsl:template match="sms" mode="inGroup">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
<xsl:template match="sms"/>
</xsl:stylesheet>
<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>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
concat(substring($string1, 1 div $condition),
substring($string2, 1 div not($condition))
)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:for-each-group select="sms" group-by=
"concat(@contact_name,'+',
if(starts-with(@address,'+'))
then substring(@address, 4)
else @address
)">
<sms contact_name="{@contact_name}">
<xsl:apply-templates select="current-group()"/>
</sms>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="sms">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
</xsl:stylesheet>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
这种等价性源自这样一个事实,即1div true()
与1div1
相同,这是1
,而1div false()
与1div0
相同,这是一个数(正)无穷大
另外,对于任何字符串$s
,子字符串($s,无穷大)
的值就是空字符串。当然,对于任何字符串$s
,子字符串($s,1)
的值就是字符串$s
本身
II。XSLT 2.0解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kContactByNameAddress" match="sms"
use="concat(@contact_name,'+',@address)"/>
<xsl:template match=
"sms[generate-id()
=
generate-id(key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)
[1]
)
]
">
<sms contact_name="{@contact_name}">
<xsl:apply-templates mode="inGroup"
select="key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)"/>
</sms>
</xsl:template>
<xsl:template match="sms" mode="inGroup">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
<xsl:template match="sms"/>
</xsl:stylesheet>
<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>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
concat(substring($string1, 1 div $condition),
substring($string2, 1 div not($condition))
)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:for-each-group select="sms" group-by=
"concat(@contact_name,'+',
if(starts-with(@address,'+'))
then substring(@address, 4)
else @address
)">
<sms contact_name="{@contact_name}">
<xsl:apply-templates select="current-group()"/>
</sms>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="sms">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
</xsl:stylesheet>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
在同一XML文档(如上)上应用此(更简单!)XSLT 2.0转换时,将生成相同的正确输出:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kContactByNameAddress" match="sms"
use="concat(@contact_name,'+',@address)"/>
<xsl:template match=
"sms[generate-id()
=
generate-id(key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)
[1]
)
]
">
<sms contact_name="{@contact_name}">
<xsl:apply-templates mode="inGroup"
select="key('kContactByNameAddress',
concat(@contact_name,'+',@address)
)"/>
</sms>
</xsl:template>
<xsl:template match="sms" mode="inGroup">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
<xsl:template match="sms"/>
</xsl:stylesheet>
<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>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
concat(substring($string1, 1 div $condition),
substring($string2, 1 div not($condition))
)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:for-each-group select="sms" group-by=
"concat(@contact_name,'+',
if(starts-with(@address,'+'))
then substring(@address, 4)
else @address
)">
<sms contact_name="{@contact_name}">
<xsl:apply-templates select="current-group()"/>
</sms>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="sms">
<message type="{@type}">
<xsl:value-of select="@body"/>
</message>
</xsl:template>
</xsl:stylesheet>
<sms contact_name="Person1">
<message type="1">Some text</message>
<message type="2">Some text</message>
<message type="1">Some text</message>
</sms>
<sms contact_name="Person2">
<message type="2">Some text</message>
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="Person3">
<message type="1">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="2">Some text</message>
<message type="2">Some text</message>
</sms>
<sms contact_name="jared">
<message type="1">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="2">Some text</message>
</sms>
<sms contact_name="(Unknown)">
<message type="1">Some text</message>
</sms>
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
问得好,+1。现在,您将能够学习并应用使用复合键的明钦语分组。@_Jared:您需要解释(更好地通过编辑问题)国家代码前缀的规则:是2位数还是3位数,还是不同位数?如果是后者,那么解决方案应该提供所有可能的国家代码的列表。@(u Dimitre)-抱歉,希望我现在已经说得更清楚了。在我遇到这个障碍之前,我是如此的接近于让它自己工作。非常感谢你的帮助!你能提供一份国家/网络代码列表或告诉我们至少一个代码由多少位数组成吗?@_Empo我没有说清楚吗?也许不行,如果有帮助的话,我会添加一个列表。谢谢。你学识渊博!非常感谢你的回答。唉,我想我的例子错了,对此我深表歉意!我编辑了我的问题来更新这个。哥们,这真是太棒了,关于它做什么的解释是史诗般的。非常感谢,我想我可以从这里开始:)@Jared:不客气。如果问题中有其他信息,那么解决方案可能会简单得多——例如,如果已知所有电话号码(不带国家代码)都具有相同的固定长度。如果您的情况是这样,请确认,我很高兴发布更简单的解决方案。不幸的是,大多数数字可能从7(不包括国家或网络代码)到8,然后您会收到特定于网络的消息或比赛号码,通常为3-4个字符。我最后做的是将子字符串的else条件改为2div,它表示“021”,4表示“+642”。不过,我认为我现在很好,我把适当的XML数据放进去,结果很好。最好使用XSLT2.0,我必须亲自调查一下。再次感谢你的帮助!