0

I have been working on the following xml:

<?xml version="1.0" encoding="utf-8" ?>
 <root>
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     .....
     xmlns:dc="http://purl.org/dc/terms/">

  <skos:Concept rdf:about="http://aims.fao.org/aos/agrovoc/c_26321">
     .....
   <skos:prefLabel xml:lang="en">Abies mariesii</skos:prefLabel>
   <skos:broader rdf:resource="http://aims.fao.org/aos/agrovoc/c_10"/>
  </skos:Concept>

  <skos:Concept rdf:about="http://aims.fao.org/aos/agrovoc/c_33272">
     .....
   <skos:prefLabel xml:lang="en">Abies numidica</skos:prefLabel>
   <skos:broader rdf:resource="http://aims.fao.org/aos/agrovoc/c_10"/>
  </skos:Concept>

     .....

  <skos:Concept rdf:about="http://aims.fao.org/aos/agrovoc/c_5886">
     .....
   <skos:prefLabel xml:lang="en">Pinaceae</skos:prefLabel>
     .....
   <skos:narrower rdf:resource="http://aims.fao.org/aos/agrovoc/c_10"/>        
  </skos:Concept>

  <skos:Concept>
   <skos:narrower rdf:resource="http://aims.fao.org/skosmos/agrovoc/en/page/c_1322232213779"/>
   <skos:narrower rdf:resource="http://aims.fao.org/skosmos/agrovoc/en/page/c_19"/>
     .....
   <skos:prefLabel xml:lang="en">Abies</skos:prefLabel>
     .....
   <skos:closeMatch>

     .....

 </rdf:RDF>

The whole xml can be accessed here: http://128.199.159.143/merged-file.xml

And I have the following XSLTs (based from xslt get element value based on attribute which is referenced in another node tree) here:

<?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   .....
 xmlns:void="http://rdfs.org/ns/void#">
 <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
 <xsl:key name="concepts-by-about" match="//skos:Concept" use="@rdf:about" />

  <xsl:template match="root">
   <xsl:for-each select="rdf:RDF">
   <xsl:text>START HERE</xsl:text>
   <xsl:text>&#13;&#10;</xsl:text>
   <xsl:text>=LDR  00000nam  2200000Ia 4500</xsl:text>
   <xsl:text>&#13;&#10;</xsl:text>
   <xsl:apply-templates select="skos:Concept/skos:broader" />
   <xsl:text>&#13;&#10;</xsl:text>
   <xsl:apply-templates select="skos:Concept/skos:narrower" />
   <xsl:text>&#13;&#10;</xsl:text>
   </xsl:for-each>
  </xsl:template>

  <xsl:template match="//skos:broader[key('concepts-by-about', @rdf:resource)]">       
   <xsl:text>=301  \\$abroader$b</xsl:text><xsl:value-of select="key('concepts-by-about', @rdf:resource)/skos:prefLabel[@xml:lang='en']" />
   <xsl:text>$c</xsl:text>
   <xsl:value-of select="./@rdf:resource" />
   <xsl:text>&#13;&#10;</xsl:text>   
  </xsl:template>           

  <xsl:template match="text()" />

  <xsl:template match="//skos:narrower[key('concepts-by-about', @rdf:resource)]">       
   <xsl:text>=302  \\$anarrower$b</xsl:text><xsl:value-of select="key('concepts-by-about', @rdf:resource)/skos:prefLabel[@xml:lang='en']" />
   <xsl:text>$c</xsl:text>
   <xsl:value-of select="./@rdf:resource" />
   <xsl:text>&#13;&#10;</xsl:text>   
  </xsl:template>           

  <xsl:template match="text()" />

  <xsl:template match="skos:Concept/skos:narrower/skos:Concept/skos:prefLabel[@xml:lang='en']">
   <xsl:text>=302  \\$anarrower$b</xsl:text><xsl:value-of select="." />
   <xsl:text>$c</xsl:text>
   <xsl:value-of select="../@rdf:about" />
   <xsl:text>&#13;&#10;</xsl:text>
  </xsl:template>

 </xsl:stylesheet>

With this xslt, I am getting the following:

START HERE
=LDR  00000nam  2200000Ia 4500
=301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10
=301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10
  (more =301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10) ...
=301  \\$abroader$bPinaceae$chttp://aims.fao.org/aos/agrovoc/c_5886

which is fine for me because, it is what I wanted with the xml, based from http://aims.fao.org/skosmos/agrovoc/en/page/c_10 which Pinaceae is a broader concept. However, 'Abies' is repeated several times, so how do I remove these duplicates and print it as another value:

=400  \\$apreferredterm$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10
Community
  • 1
  • 1
schnydszch
  • 435
  • 5
  • 19
  • 3
    Note that using XSLT on an RDF/XML document is inherently risky. There are lots of RDF/XML graphs that would contain exactly the same RDF content that *won't* work with whatever XSLT you end up with. The same RDF graph can be serialized in XML lots of different ways. See [this answer](http://stackoverflow.com/a/17052385/1281433) for a bit more about the issues with XML-based techniques applied to RDF/XML. – Joshua Taylor Aug 17 '15 at 13:09
  • Can you update your question with data that actually outputs your example output? After fixing the XML and XSLT to make it valid, I just get `=LDR 00000nam 2200000Ia 4500` (after _START HERE_). It is easier to help you when we have an actual working example of your issue. – Abel Aug 17 '15 at 14:02
  • Hi Joshua, my follow-up question is how do I output my data sets in a tabular or linear form? or such in a form as this: http://aims.fao.org/skosmos/agrovoc/en/page/c_10 – schnydszch Aug 17 '15 at 14:14
  • Hi! Abel the xml is http://128.199.159.143/merged-file.xml while the xslt that I've been working on is here: http://128.199.159.143/skos70.xsl – schnydszch Aug 17 '15 at 14:21

1 Answers1

1

I had a look at your referenced stylesheet and there's this line:

<xsl:template match="//skos:broader[key('concepts-by-about', @rdf:resource)]">

Since keys are global, and there is at least one matching node to the key, the construct [key(...)] will always be true (in a predicate, if it matches a node, it counts as "true"). You can see this for yourself if you try the following at any level:

<xsl:value-of select="count(//skos:broader[key('concepts-by-about', @rdf:resource)])" />

It will show you that there are 51 nodes matching. Probably not your intent.

It seems to me that you actually want to match skos:broader elements that have a parent (or an ancestor) that matches the @rdf-resource attribute of the current node with the @rdf:about attribute of skos:Concept. You can do that as follows:

<xsl:template
    match="skos:broader[@rdf:resource = ancestor::skos:Concept/@rdf:about]">

After I change this there is only one of the following in the output:

=301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10

Then, inside that template, you do:

<xsl:value-of
    select="key('concepts-by-about', @rdf:resource)/skos:prefLabel[@xml:lang = 'en']" />

This will return the first global value matched by the key. Again, it appears to me that you actually want the ancestor skos:Concept here, but I'm guessing. If so, it should be (ignoring the match on @rdf:about, because we already know it is a match):

<xsl:value-of select="ancestor::skos:Concept/skos:prefLabel[@xml:lang = 'en']" />

Furthermore, there are a few occasions where you have a match pattern that starts with //, this has no effect. It means "starting from the root, any node, at any level, that matches what follows". But a pattern is already global anyway, so it has no effect, except that you ask the processor to do an expensive lookup each time it encounters that pattern. This is true for the key and for some matching templates.

I think that your use of the key-function is not necessary for what you are trying to accomplish, but I have to admit that I do not fully understand the width of your requirements.

Abel
  • 56,041
  • 24
  • 146
  • 247
  • I have actually abandoned this strategy of translating my data set. But I can go back to it again. Yes I would like to match skos:broader's rdf:resource (e.g. root/rdf:RDF/skos:Concept/skos:broader[@rdf:resource="http://aims.fao.org/skosmos/agrovoc/en/page/c_5886"]) to a Skos:Concept @rdf:about (root/rdf:RDF/skos:Concept[@rdf:about="http://aims.fao.org/aos/agrovoc/c_5886"]) and then if they matched, I get the value of the xml:lang='en'. I tried both adding the templates, but I seem to be missing something. Here is the current template for reference: http://128.199.159.143/skos73.xsl – schnydszch Aug 24 '15 at 12:56
  • @schnydszch: your stylesheet works inasmuch I understand the requirements, the "301" line is now output once with "Abies" as `=301 \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10`. But if you can, you should switch to XSLT 2.0, where the same task is _much_ easier using `xsl:for-each-group` syntax. – Abel Aug 25 '15 at 22:45
  • @schnydszch: if my solution helped you, then feel free to upvote and/or accept it as an answer ;) – Abel Aug 28 '15 at 08:40