Question

I have this xml

<?xml version='1.0' encoding='utf-8'?>
<DATA>
  <PERSONS>
    <PERSON id="792226" member_id="53534">
      <FNAME>Alfred</FNAME>
      <MNAME> C  </MNAME>
      <LNAME> Kenneth </LNAME>
      <EMAIL> ac1@abc.com </EMAIL>
      <USER_ROLES>
        <ROLE> Abstract </ROLE_NAME>
      </USER_ROLES>
    </PERSON>
    <PERSON id="792319" member_id="34526">
      <FNAME> Adam </FNAME>
      <MNAME> F  </MNAME>
      <LNAME> Robert </LNAME>
      <EMAIL> adam@xyz.com </EMAIL>
      <USER_ROLES>
        <ROLE> General</ROLE>
        <ROLE> Reviewer </ROLE>
      </USER_ROLES>
      <AREAS_OF_EXPERTISE>
        <EXPERTISE> Dynamics</EXPERTISE>
        <EXPERTISE> Engineering </EXPERTISE>
        <EXPERTISE> Exploration</EXPERTISE>
      </AREAS_OF_EXPERTISE>
    </PERSON>
 </PERSONS>
</DATA>

would like to convert as html table using xslt. I want to pull only id, member_id, fname, Role and Expertise..Any help would be appreciated.

Updated : I have applied this xslt

<xsl:template match="/">
 <html>
 <head>
 </head>
 <body>
  <table border="1">
    <tr>
        <th>ID</th>
        <th>Member ID</th>
        <th>First Name</th>
        <th>ROLE</th>
        <th>Expertise</th>

    </tr>
        <xsl:for-each select="DATA/PERSONS/PERSON">
        <tr>
                <td><xsl:value-of select="@id"/></td>
                <td><xsl:value-of select="@member_id"/></td>
                <td><xsl:value-of select="FNAME"/></td>
                <td><xsl:value-of select="USER_ROLES/ROLE"/></td>
                <td><xsl:value-of select="AREAS_OF_EXPERTISE/EXPERTISE"/></td>

        </tr>   
        </xsl:for-each>             
</table>
</body>
</html>

But I am not sure how to read roles and expertise when it is more than one node. It always shows first node only. if role or expertise are more then one then it should be in a new row with id, memberid, fname and email.

I would like to display as

Edited : It should display in new row for each role and expertise. So, For id 792319, it will 5 rows, 2 rows for role and 3 rows for expertise. Little weird, but that is the way they wanted. Some records may not have no roles and expertise.'

I tried to upload image what I want, but I dont have that much reputation to do that :)

EDIT :

Finally, I have developed this xslt. I got idea from Michael suggestion. Hope this will help others. This xslt read all the records together.

<xsl:template match="/">
 <html>
 <head>
 </head>
 <body>
   <table border="1">
    <tr>
        <th>ID</th>
        <th>Member ID</th>
        <th>First Name</th>
        <th>Email</th>
        <th>ROLE</th>
        <th>Expertise</th>

    </tr>
<xsl:for-each select="DATA/PERSONS/PERSON">

                <xsl:choose>
                  <xsl:when test="count(USER_ROLES) > 0 or count(AREAS_OF_EXPERTISE) > 0">
                  <xsl:for-each select="USER_ROLES/ROLE" >
                      <tr>
                        <td><xsl:value-of select="../../@id"/></td>
                        <td><xsl:value-of select="../../@member_id"/></td>
                        <td><xsl:value-of select="../../FNAME"/></td>
                        <td><xsl:value-of select="../../EMAIL"/></td>
                        <td><xsl:value-of select="self::ROLE"/></td>
                        <td></td>
                        </tr>
                    </xsl:for-each>
                    <xsl:for-each select="AREAS_OF_EXPERTISE/EXPERTISE" >
                      <tr>
                        <td><xsl:value-of select="../../@id"/></td>
                        <td><xsl:value-of select="../../@member_id"/></td>
                        <td><xsl:value-of select="../../FNAME"/></td>
                        <td><xsl:value-of select="../../EMAIL"/></td>
                        <td></td>
                        <td><xsl:value-of select="self::EXPERTISE"/></td>
                        </tr>
                    </xsl:for-each>
                  </xsl:when>
                            <xsl:otherwise>
                            <tr>
                                <td><xsl:value-of select="@id"/></td>
                                <td><xsl:value-of select="@member_id"/></td>
                                <td><xsl:value-of select="FNAME"/></td>
                                <td><xsl:value-of select="EMAIL"/></td>
                                <td></td>
                                <td></td>
                            </tr>
                          </xsl:otherwise>      
                 </xsl:choose>

        </xsl:for-each> 
  </table>
  </body>
  </html>
</xsl:template>         
Was it helpful?

Solution

Would a table like this satisfy your requirements?

enter image description here


Edit:

It is very simple to produce a table like you want:

enter image description here

XSLT 1.0

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
<table border="1">
    <tr>
        <th>ID</th>
        <th>Member ID</th>
        <th>First Name</th>
        <th>e-Mail</th>
        <th>Role</th>
        <th>Expertise</th>
    </tr>
    <xsl:for-each select="DATA/PERSONS/PERSON/USER_ROLES/ROLE | DATA/PERSONS/PERSON/AREAS_OF_EXPERTISE/EXPERTISE">
        <tr>
            <td><xsl:value-of select="../../@id"/></td>
            <td><xsl:value-of select="../../@member_id"/></td>
            <td><xsl:value-of select="../../FNAME"/></td>
            <td><xsl:value-of select="../../EMAIL"/></td>
            <td><xsl:value-of select="self::ROLE"/></td>
            <td><xsl:value-of select="self::EXPERTISE"/></td>
        </tr>
    </xsl:for-each>
</table>
</xsl:template>

</xsl:stylesheet>

However, if a person has neither a role nor an expertise, they will not be included.


Edit 2:

To append the people with no roles nor expertise to the above table, just add another row for each such person. Here's the modified stylesheet:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
<table border="1">
    <tr>
        <th>ID</th>
        <th>Member ID</th>
        <th>First Name</th>
        <th>e-Mail</th>
        <th>Role</th>
        <th>Expertise</th>
    </tr>
    <xsl:for-each select="DATA/PERSONS/PERSON/USER_ROLES/ROLE | DATA/PERSONS/PERSON/AREAS_OF_EXPERTISE/EXPERTISE">
        <tr>
            <td><xsl:value-of select="../../@id"/></td>
            <td><xsl:value-of select="../../@member_id"/></td>
            <td><xsl:value-of select="../../FNAME"/></td>
            <td><xsl:value-of select="../../EMAIL"/></td>
            <td><xsl:value-of select="self::ROLE"/></td>
            <td><xsl:value-of select="self::EXPERTISE"/></td>
        </tr>
    </xsl:for-each>
    <xsl:for-each select="DATA/PERSONS/PERSON[not(USER_ROLES) and not(AREAS_OF_EXPERTISE)]">
        <tr>
            <td><xsl:value-of select="@id"/></td>
            <td><xsl:value-of select="@member_id"/></td>
            <td><xsl:value-of select="FNAME"/></td>
            <td><xsl:value-of select="EMAIL"/></td>
            <td/>
            <td/>
        </tr>
    </xsl:for-each>
</table>
</xsl:template>

</xsl:stylesheet>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top