我编写了一个XSLT,它应该添加一个或多个skos:父rdf:Description元素中的较窄元素。这是一个起始的xml:
<rdf:Description rdf:about="http://schema.xxx.com/ns/vocabulary-structure/AAA">
<rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
<skos:prefLabel xml:lang="en">AAA</skos:prefLabel>
<skos:broader rdf:resource="http://schema.xxx.com/ns/vocabulary-structure/AA"/>
</rdf:Description>
我希望为xml中的每个较窄元素添加一个元素:
<rdf:Description rdf:about="http://schema.xxx.com/ns/vocabulary-structure/AAA">
<skos:narrower rdf:resource="http://schema.xxx.com/ns/vocabulary-structure/AAAA"/>
<rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
<skos:prefLabel xml:lang="en">AAA</skos:prefLabel>
<skos:broader rdf:resource="http://schema.xxx.com/ns/vocabulary-structure/AA"/>
</rdf:Description>
我需要这样做才能指定skos:wide和skos:更窄的关系(我使用的词汇工具只存储skos:更广泛)。
我写的xsl就是这样做的。然而,虽然结果接近我想要的,但它有一个缺陷。如果元素AAA除了AAAA之外还有一个更窄的元素AAAB,那么我得到一个单独的 rdf:Description元素:
<rdf:Description rdf:about="http://schema.xxx.com/ns/vocabulary-structure/AAA">
<skos:narrower rdf:resource="http://schema.xxx.com/ns/vocabulary-structure/AAAB"/>
<rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
<skos:prefLabel xml:lang="en">AAA</skos:prefLabel>
<skos:broader rdf:resource="http://schema.xxx.com/ns/vocabulary-structure/AA"/>
</rdf:Description>
我想要的是两个skos:更窄的指向AAAA,指向AAAB的指向同一个AAA元素,而不是两个单独的元素。
这是xslt的(我希望)相关部分。任何人都可以建议我做错了吗?
<xsl:template match="rdf:RDF/rdf:Description" mode="apply-skos-narrower">
<xsl:param name="this-concept-id"/>
<xsl:param name="narrower-concept-id"/>
<xsl:choose>
<xsl:when test="@rdf:about=$this-concept-id">
<xsl:copy>
<xsl:copy-of select="@*|node()"/>
<skos:narrower>
<xsl:attribute name="rdf:resource">
<xsl:value-of select="$narrower-concept-id"/>
</xsl:attribute>
</skos:narrower>
<xsl:copy-of select="node()"/>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
感谢您的评论。以下是所要求的完整xslt。我确信我在这里误解了关于递归是如何工作的,所以任何指导都会非常感激。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="1.0"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:skos="http://www.w3.org/2004/02/skos/core#"
>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Store the vocabulary identifier as a variable -->
<xsl:variable name="vocabulary-id" select = "//rdf:Description[child::rdf:type[@rdf:resource='http://www.w3.org/2002/07/owl#Ontology']]/@rdf:about" />
<!-- Replace the massive collection of namespace declarations provided by EVN with a more sensible minimal set, then call the first processing template. -->
<xsl:template match="/">
<rdf:RDF xmlns:opencyc="http://sw.opencyc.org/concept/"
xmlns:freebase="http://rdf.freebase.com/ns/"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:skos="http://www.w3.org/2004/02/skos/core#"
xmlns:dbpedia="http://dbpedia.org/resource/"
xmlns:sesame="http://www.openrdf.org/schema/sesame#"
xmlns:cycAnnot="http://sw.cyc.com/CycAnnotations_v1#"
xmlns:ctag="http://commontag.org/ns#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:cyc="http://sw.cyc.com/concept/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<!-- Copy the header and Concept Scheme sections - these are fine -->
<xsl:apply-templates select="/rdf:RDF/rdf:Description" mode="process-vocabulary-header"/>
<xsl:apply-templates select="/rdf:RDF/rdf:Description" mode="process-concept-scheme"/>
<!-- Now process all of the other concepts -->
<xsl:apply-templates select="/rdf:RDF/rdf:Description" mode="process-other-concepts"/>
</rdf:RDF>
</xsl:template>
<!-- Process the vocabulary header information -->
<xsl:template match="rdf:RDF/rdf:Description" mode="process-vocabulary-header">
<xsl:if test="rdf:type[@rdf:resource='http://www.w3.org/2002/07/owl#Ontology']">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
<!-- Process the ConceptScheme element -->
<xsl:template match="rdf:Description" mode="process-concept-scheme">
<xsl:if test="rdf:type[@rdf:resource='http://www.w3.org/2004/02/skos/core#ConceptScheme']">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
<xsl:template match="rdf:RDF/rdf:Description" mode="process-other-concepts">
<xsl:choose>
<!-- When we are in the ConceptScheme element, we can get the concepts that have hasTopConcept elements and set the complementary topConceptOf elements -->
<xsl:when test="rdf:type[@rdf:resource='http://www.w3.org/2004/02/skos/core#ConceptScheme']">
<xsl:for-each select="skos:hasTopConcept">
<xsl:apply-templates select="/rdf:RDF/rdf:Description" mode="apply-top-concepts">
<xsl:with-param name="top-concept-id" select="@rdf:resource"/>
</xsl:apply-templates>
</xsl:for-each>
<!-- Finally, find the elements with skos:broader elements and set their complementary skos:narrower elements -->
</xsl:when>
<xsl:when test="skos:broader">
<xsl:apply-templates select="/rdf:RDF/rdf:Description" mode="apply-skos-narrower">
<xsl:with-param name="this-concept-id" select="skos:broader/@rdf:resource"/>
<xsl:with-param name="narrower-concept-id" select="./@rdf:about"></xsl:with-param>
</xsl:apply-templates>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- Add the topConceptOf element to the right concepts -->
<xsl:template match="rdf:RDF/rdf:Description" mode="apply-top-concepts">
<xsl:param name="top-concept-id"/>
<xsl:choose>
<xsl:when test="@rdf:about=$top-concept-id">
<xsl:copy>
<xsl:copy-of select="@*"/>
<skos:topConceptOf>
<xsl:attribute name="rdf:resource">
<xsl:value-of select="$vocabulary-id"/>
</xsl:attribute>
</skos:topConceptOf>
<xsl:copy-of select="node()"/>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- Add the skos:narrower element to the right concepts -->
<xsl:template match="rdf:RDF/rdf:Description" mode="apply-skos-narrower">
<xsl:param name="this-concept-id"/>
<xsl:param name="narrower-concept-id"/>
<xsl:choose>
<xsl:when test="@rdf:about=$this-concept-id">
<xsl:copy>
<xsl:copy-of select="@*|node()"/>
<skos:narrower>
<xsl:attribute name="rdf:resource">
<xsl:value-of select="$narrower-concept-id"/>
</xsl:attribute>
</skos:narrower>
<xsl:copy-of select="node()"/>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:0)
首先警告:你不应该使用像XSLT这样的纯XML处理工具来处理RDF-XML,除非别无选择。对于相同的底层RDF图,有许多等效的XML表示,使用理解图结构的正确RDF工具会更好。
那就是说...我认为你可以通过一个能让你通过skos:broader
查找rdf:resource
元素的密钥以更简单的方式实现你想要的。然后在您处理rdf:Description
X的时候,以X作为对象来查找更宽的三元组,并创建相应的“#34”更小的&#34;逆。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="1.0"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:skos="http://www.w3.org/2004/02/skos/core#"
>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="broaderByObject" match="skos:broader" use="@rdf:resource" />
<!-- identity template - copy everything as-is except for overrides -->
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="rdf:Description">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each select="key('broaderByObject', @rdf:about)">
<!-- the object of the narrower is the subject from the broader -->
<skos:narrower rdf:resource="{../@rdf:about}" />
</xsl:for-each>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
同样的原则适用于顶级概念 - 添加密钥
<xsl:key name="topConByObject" match="skos:hasTopConcept" use="@rdf:resource" />
并查找创建反转的键
<xsl:if test="key('topConByObject', @rdf:about)">
<skos:topConceptOf rdf:resource="{$vocabulary-id}" />
</xsl:if>