![]() |
![]() | ![]() | ![]() | Altova Mailing List Archives>Archive Index >comp.text.xml Archive Home >Recent entries >Thread Prev - XSL Transformation of .owl file [Thread Next] Re: XSL Transformation of .owl fileTo: NULL Date: 4/1/2005 2:22:00 AM > Thanks for the extensive response, I've just recently started with XML and > XSLT so it's much appreciated. This is so broken I don't know where to start ! You just can't process an RDF document like this in XSLT. Teaching students in this way is just wrong, wrong, wrong. You're using entirely the wrong toolset here, it'll end badly, and you won't learn either technology. You'd be far better off being taught XSLT with some much simpler XML, then maybe processing this sort of document through Jena. It is a very bad way to teach you, if you're being taught XSLT and OWL simultaneously. I don't know how much you do know, but I know of no way in which these could be taught together. Unless you _understand_ XML (you really grok it), then I can't even begin to explain what OWL is about. If you're trying to work with OWL, then XSLT is the wrong tool to use. Unless you've got _some_ experience, I can barely even explain why it's difficult! So I'll assume you're new to the whole lot you're learning XML / XSLT. This is a good place to be - it's useful stuff. Don't worry about OWL though. I'm assuming you're being taught this because it's a substitute for DTDs. Now I have big reservations about this - OWL is quite complicated and it's going to scare the feet off any XML newbie. Particularly it's based around the RDF data model and you just can't process that (sensibly) with XSLT. As an XSLT text, then I recommend Michael Kay's book "XSLT" <http://www.amazon.co.uk/exec/obidos/ASIN/0764543814/codesmiths> Jeni Tennison's "Beginning XSLT" is also good, and perhaps better as an approachable tutorial <http://www.amazon.co.uk/exec/obidos/ASIN/1590592603/codesmiths> Sal Mangano's "XSLT Cookbook" is a valuable text for commercial developers with problems to fix, but it will terrify learners! Now I'm still unclear what you're being asked to do here. We can find the courses trivially <xslt:template name="extract-courses-details" > <ul> <xslt:for-each select="//ont:Course" > <li> <xslt:call-template name="extract-course-details" > <xslt:with-param name="Course" select="." /> </xslt:call-template> </li> </xslt:for-each> </ul> </xslt:template> Then for your first example, we can use some simple "XML style" XSLT code to show the course details within this. <xslt:template name="extract-course-details" > <xslt:param name="Course" select="/.." /> <!-- print CourseName --> <p>Course: <xslt:value-of select="$Course/ont:CourseName" /></p> <!-- print ProgrammeName (the quick hack way) --> <p>Programme: <xslt:value-of select="$Course/ont:isCourseOf//ont:ProgrammeName" /></p> </xslt:template> Now there are a few issues with this. First of all there are some cardinality issues (how many programmes can a course belong to etc). It's important to remember these when working with XML / XSLT because most code you write will be working with a node set (potentially many data items) and your natural assumption is often that you're only looking for one. Then one day your input data contains more than one, and your application barfs. So either be able to _prove_ that the cardinality is that of a single value, or else code it to deal correctly with the multiple sets. This is particularly the case for library code. <xslt:template name="extract-course-details" > <xslt:param name="Course" select="/.." /> <!-- print CourseName --> <p>Course: <xslt:value-of select="$Course/ont:CourseName" /></p> <!-- find out which Programme Course belongs to (not quite so hacky) --> <xslt:variable name="Programme" select="$Course/ont:isCourseOf/*[1]" /> <!-- print ProgrammeName --> <p>Programme: <xslt:value-of select="$Programme/ont:ProgrammeName" /></p> <!-- find out which University Programme belongs to --> <!-- print UniversityName --> <p>University: <xslt:value-of select="$Programme/ont:isProgrammeOf/ont:University/ont:UniversityName" /></p> </xslt:template> So in the example above, I've coded it to _ONLY_ accept the first one (discarding others). Not only would we have to deal with the multiples through some form of loop, but we'd have to make sure that the Programme and University selections stayed in synchronisation (hence the use of the variable) - so if you can do, do it the simple way, but make sure that it's demonstrably valid to do so in the future as well. Now notice the use of "//" within the XPath expressions. This is a dangerous technique ! (it's less hazardous to use it at the start of an expression). It's rarely necessary to use it in an XML context - it's needed here because of the subclassing of <Programme> as <ProgrammeAI> There's no way to implement this in XSLT, so we have to use this "wildcard" approach. My skin crawls to do this - it's a huge source of future errors. It's likely to be reliable to do this here, because <ProgrammeName> is likely (a risky assumption!) to only ever apply to <Programme> A more sophisticated ontology (arguably better) might have a <name> property for each of these elements. Then my crude assumption would start to fail - it would depend on the scope of what <isCourseOf> can apply to. Incidentally, a couple of convention notes: - <programmeName> would be conventional, because properties begin with a lowercase as a human readability issue. - You don't need the data typing sprinkled all over the instance data. - Watch your indentation - it can make code readability much easier. So how do we solve the "big problem", that of how to process this whole model, cardinality and RDF issues too ? Well try this example template. I've commented what I could, so this is hopefully an example of "complex RDF-processing XML for people who already know some XML" that's useful to you. I'm sorry this example is so clunky - this sort of processing just doesn't fit XSLT's model. In contrast, the ECTS example would be pretty easy, because that's expressable in "simple XML" <xsl:for-each select="//myns:Course[myns:CourseECTS > 5.0]" > Of course, some use of rdf:about or simply changing the serialiser to some other valid XML serialisations would break things again - you ought to be using a real RDF tool here (like Jena), not an XML tool. _Please_ post follow up comments to this. I'd like to know just what you're after and whether this is useful to you. <!-- These have global scope, so we place them outside the templates Note that we have to account for the subclassing here, but after this we can ignore it. --> <xsl:variable name="All-Programmes" select="//myns:Programme | //myns:ProgrammeAI" /> <xsl:variable name="All-Universities" select="//myns:University" /> <xsl:template name="extract-course-details-for-RDF-model" > <xsl:param name="Course" select="/.." /> Course: <xsl:value-of select="$Course/myns:CourseName" /> <!-- The RDF-capable version --> <!-- Find the set of Programmes for this Course These are any elements which are either children of isCourseOf or parents of hasCourse We can't test the element name itself, because of subclassing changing the element name We either find the Programme elements directly or we retrieve them via rdf:resource as an attribute of the hasCourse element --> <xsl:variable name="Programmes-for-Course" select=" $Course/myns:isCourseOf/* | $All-Programmes [concat('#', @rdf:ID) = $Course/myns:isCourseOf/@rdf:resource] | $Course/parent::myns:hasCourse/parent::* | $All-Programmes [concat('#', @rdf:ID) = $Course/parent::myns:hasCourse/@rdf:resource] " /> <ul> <xsl:for-each select="$Programmes-for-Course" > <!-- This is optional, but we often need to do it whenever we've nested two loops (as "." scopes to the inner loop) It also makes the code clearer to read --> <xsl:variable name="Programme" select="." /> <li> Programme: <xsl:value-of select="$Programme/myns:ProgrammeName" /> <!-- find out which University(s) this Programme belongs to --> <xsl:variable name="Universities-for-Programme" select=" $Programme/myns:isProgrammeOf/* | $All-Universities[concat('#', @rdf:ID) = $Programme/myns:isProgrammeOf/@rdf:resource] | $Programme/parent::myns:hasProgramme/parent::* | $All-Universities[concat('#', @rdf:ID) = $Programme/parent::myns:hasProgramme/@rdf:resource] " /> <!-- Just a frippery to make the display neater --> <xsl:choose> <xsl:when test="count($Universities-for-Programme) > 1" > <ul> <xsl:for-each select="$Universities-for-Programme" > <li>University: <xsl:value-of select="./myns:UniversityName" /></li> </xsl:for-each> </ul> </xsl:when> <xsl:when test="count($Universities-for-Programme) = 1" > <br />University: <xsl:value-of select="$Universities-for-Programme/myns:UniversityName" /> </xsl:when> </xsl:choose> </li> </xsl:for-each> </ul> </xsl:template> | ![]() | ![]() | ![]() |
| Company | Legal | Press | Partners | Careers | Sitemap | Contact Us | Altova Blog | |||||
|
