I am trying to write a document which could help in filtering data from another XML document. E.g.
<document>
<filter>
<what>
<include>
<marital_staus/>
<ms>single</ms> <!--nog = no of groups-->
<include>
<memberofgroups/>
<gn>Football club</gn> <!--user is a member of this club-->
</include>
</include>
</what>
</filter>
<users>
<user>
<name>
<first>abc</first>
<last>xyz</last>
</name>
<dob>12/02/1987</dob>
<marital_status>married</marital_status>
<groups>
<member_of_group>Chess Club</member_of_group>
<member_of_group>Football club</member_of_group>
</groups>
</user>
<user>
<name>
<first>aaa</first>
<last>bbb</last>
</name>
<dob>14/03/1987</dob>
<marital_status>single</marital_status>
<groups>
<member_of_group>Chess Club</member_of_group>
<member_of_group>Football club</member_of_group>
</groups>
</user>
<user>
<name>
<first>fff</first>
<last>nnn</last>
</name>
<dob>12/6/1983</dob>
<marital_status>single</marital_status>
<groups>
<member_of_group>Chess Club</member_of_group>
<member_of_group>Cultural Association</member_of_group>
</groups>
</user>
</users>
</document>
What I want this code to do is to choose, first, the users who are members of Football club, and then out of those, chose the users who are single. But I cannot figure out how to write a stylesheet for this. I wrote this:
<xsl:template name="temp">
<xsl:param name="a1"/>
<xsl:param name="pro"/>
<xsl:choose>
<xsl:when test="$pro = 'marital_status'">
<xsl:for-each select="/document/users/user">
<xsl:if test="marital_status=$a1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:when test="$pro = 'memberofgroups'">
<xsl:for-each select="/document/users/user">
<xsl:for-each select="./groups/member_of_group">
<xsl:if test=".=$a1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="include">
<xsl:call-template name="temp">
<xsl:with-param name="a1">
<xsl:apply-templates select="*[2]"/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
While calling the template I pass the correct values I suppose.
Problem is I get all the users who are single, plus all the users who are members of that particular group. However I want single users who are also member of Football club. I don't want the stylesheet to be hard-coded, because I also want to do filtering based on other elements.
I can not figure out how can I save the filtered elements into something which could be used as an input for the next XPath expression. Or am I making some mistake while writing the constraints for filtering the document. Or could there be any other more appropriate way of writing a document for filtering? I will much appreciate your help.
Use:
/*/*/user
[*[name() = name(/*/filter/*/include/*[1])]
=
/*/filter/*/include/*[2]
and
groups/*[name() = name(/*/filter/*/include/include/*[1])]
=
/*/filter/*/include/include/*[2]
]
XSLT - based verification:
<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:template match="/">
<xsl:copy-of select=
"/*/*/user
[*[name() = name(/*/filter/*/include/*[1])]
=
/*/filter/*/include/*[2]
and
groups/*[name() = name(/*/filter/*/include/include/*[1])]
=
/*/filter/*/include/include/*[2]
]
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document (with a few typos corrected):
<document>
<filter>
<what>
<include>
<marital_status/>
<ms>single</ms>
<!--nog = no of groups-->
<include>
<member_of_group/>
<gn>Football club</gn>
<!--user is a member of this club-->
</include>
</include>
</what>
</filter>
<users>
<user>
<name>
<first>abc</first>
<last>xyz</last>
</name>
<dob>12/02/1987</dob>
<marital_status>married</marital_status>
<groups>
<member_of_group>Chess Club</member_of_group>
<member_of_group>Football club</member_of_group>
</groups>
</user>
<user>
<name>
<first>aaa</first>
<last>bbb</last>
</name>
<dob>14/03/1987</dob>
<marital_status>single</marital_status>
<groups>
<member_of_group>Chess Club</member_of_group>
<member_of_group>Football club</member_of_group>
</groups>
</user>
<user>
<name>
<first>fff</first>
<last>nnn</last>
</name>
<dob>12/6/1983</dob>
<marital_status>single</marital_status>
<groups>
<member_of_group>Chess Club</member_of_group>
<member_of_group>Cultural Association</member_of_group>
</groups>
</user>
</users>
</document>
the above XPath expression is evaluated and the selected nodes (in this case just a single node) are copied to the output:
<user>
<name>
<first>aaa</first>
<last>bbb</last>
</name>
<dob>14/03/1987</dob>
<marital_status>single</marital_status>
<groups>
<member_of_group>Chess Club</member_of_group>
<member_of_group>Football club</member_of_group>
</groups>
</user>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With