tags:

views:

52

answers:

1

I want to convert the RDF/XML file into a table of 3 columns, namely "Subject" "Predicate" and "Object", these are known as RDF triples.

the RDF/XML file is as shown below:

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:h="http://www.w3.org/1999/xhtml"&gt;
  <rdf:Description rdf:about="http://www.w3.org/TR/2004/REC-rdf-mt-20040210/"&gt;
    <dc:title xmlns:dc="http://purl.org/dc/elements/1.1/"&gt;RDF Semantics - W3C Recommendation 10 February 2004</dc:title>
  </rdf:Description>
  <rdf:Description rdf:about="http://www.w3.org/TR/2004/REC-rdf-mt-20040210/"&gt;
    <dc:creator rdf:resource="#a1" xmlns:dc="http://purl.org/dc/elements/1.1/" />
  </rdf:Description>
  <rdf:Description rdf:about="#a1">
    <rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person" />
  </rdf:Description>
  <rdf:Description rdf:about="#a1">
    <foaf:name xmlns:foaf="http://xmlns.com/foaf/0.1/"&gt;Patrick Hayes</foaf:name>
  </rdf:Description>
  <rdf:Description rdf:about="#a1">
    <foaf:homepage rdf:resource="http://www.ihmc.us/users/user.php?UserID=42" xmlns:foaf="http://xmlns.com/foaf/0.1/" />
  </rdf:Description>
</rdf:RDF>

and the XSLT I have created:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
<xsl:template match="/">
<html>
<body>

  <table border="1">
    <tr bgcolor="#5d7b9d" >
      <th style="color: white">Subject</th>
      <th style="color: white">Predicate</th>
      <th style="color: white">Object</th> 
    </tr>


    <xsl:for-each select="rdf:RDF/rdf:Description">
    <tr>

      <td><xsl:value-of select="@rdf:about"/></td>

 <xsl:for-each select="*"> 
  <td><xsl:value-of select="name()"/></td>
  <td><xsl:value-of select="@rdf:resource"/>
      <xsl:value-of select="//*/rdf:Description"/>
  </td>
 </xsl:for-each>

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

via the XSLT, I was able to produce correct results for Subject, Predicate, but not for Object, because some objects are the literal encapsulated within XML elements. I tried using the xsl:value-of select="//*/rdf:Description"/ but it just returns all the literals of the document. Please help, thanks.

+1  A: 

<xsl:value-of select="*/."/> or <xsl:value-of select="*/text()"/> should do the trick, as you are in the scope of an Description and you are looking for the Description content.

Both selects return the concatenation of all texts inside the child elements. If you got a structure inside your Description elements you might have to adjust the style to incorporate this.

In more "xsl afine" style, i.e. not using for-each loops but tempates the style sheet would look like this:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
    <xsl:output method="html"/>
    <xsl:template match="/">
        <html>
            <body>

                <table border="1">
                    <tr bgcolor="#5d7b9d" >
                        <th style="color: white">Subject</th>
                        <th style="color: white">Predicate</th>
                        <th style="color: white">Object</th>
                    </tr>

                    <xsl:apply-templates select="rdf:RDF/rdf:Description"/>
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="rdf:RDF/rdf:Description">
        <tr>
            <td>
                <xsl:value-of select="@rdf:about"/>
            </td>
            <td>
                <xsl:value-of select="name()"/>
            </td>
            <td>
                <xsl:choose>
                    <xsl:when test="*/@rdf:resource">
                    <xsl:value-of select="*/."/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="*/."/>
                </xsl:otherwise>
            </xsl:choose>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

In this stylesheet, IMHO, it becomes clearer what is the actual scope of the evaluation.

If you want to be sure that only either the resource or the content is shown, and also deal with multiple elements you could modify the above style sheet as follows:

<xsl:template match="rdf:RDF/rdf:Description">
    <tr>
        <td>
            <xsl:value-of select="@rdf:about"/>
        </td>
        <td>
            <xsl:value-of select="name()"/>
        </td>
        <td>
            <xsl:apply-templates select="rdf:RDF/rdf:Description/*"/>
        </td>
    </tr>
</xsl:template>

<xsl:template match="rdf:RDF/rdf:Description/*">
    <!-- implements either or -->
    <xsl:choose>
        <xsl:when test="*/@rdf:resource">
            <xsl:value-of select="*/."/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="*/."/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
Obalix
It works finally, thanks a lot!
louis
Then it would be nice to accept the answer.
Obalix
@Obalix: What is the difference between your `<xsl:choose>` alternatives?
Tomalak