Xml 如何使用XSL将几个新元素插入到另一个元素中,保持其他所有内容不变

Xml 如何使用XSL将几个新元素插入到另一个元素中,保持其他所有内容不变,xml,xslt,rdf,Xml,Xslt,Rdf,我编写了一个XSLT,它应该在父rdf:Description元素中添加一个或多个skos:slowner元素。下面是一段起始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"/> <

我编写了一个XSLT,它应该在父rdf:Description元素中添加一个或多个skos:slowner元素。下面是一段起始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:broader和skos:broader关系。我使用的词汇表工具只存储skos:broader

我编写的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>
我想要的是让两个SKO:更窄的指向AAAA的SKO和指向AAAB的SKO位于同一个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>

首先是一个警告:除非真的没有其他选择,否则不应该使用XSLT之类的普通XML处理工具来处理RDF-XML。同一个底层RDF图有许多等价的XML表示,最好使用理解图结构的适当RDF工具

也就是说。。。我认为,使用一个键可以通过它们的rdf:resource来查找skos:wirelater元素,从而以一种非常简单的方式实现您想要的。然后,在处理rdf:Description X时,查找以X为对象的较宽的三元组并创建相应的较窄的反转非常简单

<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>

如果您创建了两个rdf:Description元素,而不是一个,这表明您的模板被调用了两次,或者另一个模板也被复制到了元素中,因此您可能需要包含更多的XSLT,以显示调用模板的方式和位置。谢谢你有和,所以子元素将在添加的更窄元素之前和之后被复制。我觉得你使这比它需要的要困难得多-我将问题归结为为为每个X-更宽-Y添加一个逆三Y-更窄-X,对吗?这非常有效,谢谢。我曾想过用钥匙,但我不知道它是怎么工作的。你很好地澄清了这一点。