首页 文章

使用XSLT将XML文件转换为RDF / XML

提问于
浏览
1

我是XSLT的新手 . 我有一个XML文件,并希望使用XSLT将其转换为RDF / XML . 实际上我找到了一个XSLT的样式表,并且在它和XML文件之间 Build 链接,结果在浏览器中显示为“text”而不是XML文件 . 我的问题是:我希望以RDF / XML格式获得转换结果,但不幸的是我得到的结果是纯文本 .

XMl文件

<xml>
<?xml-stylesheet type="text/xsl" href="qu.xsl"?>
    <person>
    <name>Joe</name>
    <website url="www.example1.com">contact1</website >
    <vote>20</vote>
    </person>
    <person>
     <name>Anna</name>
    <website url="www.example2.com">contact2</website>
     <vote>80</vote>
     </person>
     </xml>

和XSLT样式表是

<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:html="http://www.w3.org/1999/xhtml"
            xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
            xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
            xmlns:foaf="http://xmlns.com/foaf/spec/"
            xmlns:foo="http://example.com/foo#">

<xsl:template match="/">
    <rdf:RDF>
        <rdf:Description rdf:about="http://www.example.com/xml">
            <xsl:apply-templates/>
    </rdf:Description>
    </rdf:RDF>
</xsl:template>

<xsl:template match="person">
<xsl:variable name="critic"><xsl:value-of select="name"/></xsl:variable>
<xsl:variable name="criticWebsite"><xsl:value-of select="website/@url"/</xsl:variable>
<foo:hasCritic>
    <rdf:Description rdf:about="http://www.example.com/critic/{$critic}">
        <foaf:name><xsl:value-of select="name"/></foaf:name>
        <foaf:homepage>
            <rdf:Description rdf:about="http://{$criticWebsite}">
                <rdfs:label><xsl:value-of select="website"/></rdfs:label>
            </rdf:Description>
        </foaf:homepage>
    </rdf:Description>
</foo:hasCritic>
</xsl:template>

</xsl:stylesheet>

但结果是:Joe contact1 20 Anna contact2 80

2 回答

  • 0

    Your XSLT (with a typo fixed near the criticWebsite xsl:value-of):

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:html="http://www.w3.org/1999/xhtml"
                    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
                    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
                    xmlns:foaf="http://xmlns.com/foaf/spec/"
                    xmlns:foo="http://example.com/foo#">
    
      <xsl:template match="/">
        <rdf:RDF>
          <rdf:Description rdf:about="http://www.example.com/xml">
            <xsl:apply-templates/>
          </rdf:Description>
        </rdf:RDF>
      </xsl:template>
    
      <xsl:template match="person">
        <xsl:variable name="critic"><xsl:value-of select="name"/></xsl:variable>
        <xsl:variable name="criticWebsite"><xsl:value-of select="website/@url"/></xsl:variable>
        <foo:hasCritic>
          <rdf:Description rdf:about="http://www.example.com/critic/{$critic}">
            <foaf:name><xsl:value-of select="name"/></foaf:name>
            <foaf:homepage>
              <rdf:Description rdf:about="http://{$criticWebsite}">
                <rdfs:label><xsl:value-of select="website"/></rdfs:label>
              </rdf:Description>
            </foaf:homepage>
          </rdf:Description>
        </foo:hasCritic>
      </xsl:template>
    
    </xsl:stylesheet>
    

    Applied to your input XML file (with the xml-stylesheet declaration moved immediately beneath the XML declaration, and the path to the XSLT file made absolute):

    <?xml version="1.0" ?>
    <?xml-stylesheet type="text/xsl" href="file:///c:/path/to/XSLT/qu.xsl"?>
    <xml>
      <person>
        <name>Joe</name>
        <website url="www.example1.com">contact1</website >
        <vote>20</vote>
      </person>
      <person>
        <name>Anna</name>
        <website url="www.example2.com">contact2</website>
        <vote>80</vote>
      </person>
    </xml>
    

    Produces this RDF document:

    <?xml version="1.0" encoding="UTF-8"?><rdf:RDF xmlns:html="http://www.w3.org/1999/xhtml" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:foaf="http://xmlns.com/foaf/spec/" xmlns:foo="http://example.com/foo#"><rdf:Description rdf:about="http://www.example.com/xml">
      <foo:hasCritic><rdf:Description rdf:about="http://www.example.com/critic/Joe"><foaf:name>Joe</foaf:name><foaf:homepage><rdf:Description rdf:about="http://www.example1.com"><rdfs:label>contact1</rdfs:label></rdf:Description></foaf:homepage></rdf:Description></foo:hasCritic>
      <foo:hasCritic><rdf:Description rdf:about="http://www.example.com/critic/Anna"><foaf:name>Anna</foaf:name><foaf:homepage><rdf:Description rdf:about="http://www.example2.com"><rdfs:label>contact2</rdfs:label></rdf:Description></foaf:homepage></rdf:Description></foo:hasCritic>
    </rdf:Description></rdf:RDF>
    

    注意:

    • 要在Firefox中查看此内容,请右键单击输出并选择"Inspect Element",否则您将只看到"Joecontact1 Annacontact2" .

    • 这不适用于Chrome中的本地文件,因为Chrome refuses to run locally loaded XSLT . 它必须从服务器远程加载才能工作 .

  • 2

    将XML转换为RDF也可以使用XmlToRdf库在Java中完成 .

    我在github上写了一个有用的例子:https://github.com/hmottestad/XmlToRdf---Example-from-Stack-Overflow-1

    这是转换为RDF Turtle的结果

    <http://www.example1.com>
        rdfs:label  "contact1" .
    
    <http://www.example2.com>
        rdfs:label  "contact2" .
    
    <http://www.example.com/critic/Anna>
        a              foaf:Person ;
        foaf:homepage  <http://www.example2.com> ;
        foaf:name      "Anna" ;
        foaf:vote      "80" .
    
    <http://www.example.com/critic/Joe>
        a              foaf:Person ;
        foaf:homepage  <http://www.example1.com> ;
        foaf:name      "Joe" ;
        foaf:vote      "20" .
    
    [ a              <http://example.com/xml> ;
      foo:hasCritic  <http://www.example.com/critic/Anna> ,     <http://www.example.com/critic/Joe>
    ] .
    

    使用以下java代码

    public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
    
        XmlToRdfAdvancedJena build = Builder.getAdvancedBuilderJena()
    
            // set base namesapce to the foaf namespace
            .setBaseNamespace(FOAF.NS, Builder.AppliesTo.bothElementsAndAttributes)
    
            // <foaf:person> should be renamed to <foaf:Person> (setBaseNamespace is applied first :)
            .renameElement(FOAF.Person.toString().toLowerCase(), FOAF.Person.toString())
    
            // used foaf:homepage instead of website
            .renameElement(FOAF.NS + "website", FOAF.homepage.toString())
    
            // build an IRI for our <foaf:Person> tags (rename is applied first :)
            // IRI should be "http://www.example.com/critic/" + the contents of <foaf:name>
            .compositeId(FOAF.Person.toString()).fromElement(FOAF.name.toString()).mappedTo((elments, attributes) -> "http://www.example.com/critic/" + elments.get(FOAF.name.toString()))
    
            // not everything should use the foaf namespace, so rename our root xml tag to http://example.com/xml
            .renameElement(FOAF.NS + "xml", "http://example.com/xml")
    
            // insert foo:hasCritic instead of the default xmlToRdf:hasChild predicate between the root <xml> tag and the <foaf:Person>
            .insertPredicate("http://example.com/foo#hasCritic").betweenAnyParentAndSpecificChild(FOAF.Person.toString())
            .build();
    
        Model model = build
            .convertForPostProcessing(new FileInputStream("input.xml"))
    
            // we need to do a bit of post processing using SPARQL
            // this sparql adds foaf:homepage to person based on the "url" attribute in the <website> elements
            // it also uses the inner text of the <website> tag as the rdfs:label og the homepage
            .mustacheTransform(new ByteArrayInputStream(String.join("\n",
                "insert{",
                "   ?person <{{{foafHomepage}}}> ?urlResource.",
                "  ?urlResource <{{rdfsLabel}}> ?contact.",
                "}",
                "where{",
                "   ?a a <{{{foafHomepage}}}>;",
                "       <http://xmlns.com/foaf/0.1/url> ?url ; ",
                "       <{{{hasValue}}}> ?contact . ",
    
                "   ?person ?prop ?a.",
                "    BIND( IRI(CONCAT(\"http://\",?url)) as ?urlResource).",
                "}"
    
            ).getBytes("utf-8")), new Object() {
                String foafHomepage = FOAF.homepage.toString();
                String rdfsLabel = RDFS.label.toString();
    
                String hasValue = "http://acandonorway.github.com/XmlToRdf/ontology.ttl#hasValue";
            })
    
    
            // finally we can do a bit of cleanup and remove everything related to the <website> tag
            .mustacheTransform(new ByteArrayInputStream(String.join("\n",
                "delete{",
                "   ?a <{{{hasChild}}}> ?child.",
                "   ?child ?b ?c.",
                "}",
                "where{",
                "   ?a <{{{hasChild}}}> ?child.",
                "   ?child ?b ?c.",
                "}"
    
            ).getBytes("utf-8")), new Object() {
    
                String hasChild = "http://acandonorway.github.com/XmlToRdf/ontology.ttl#hasChild";
    
            })
    
    
            .getModel();
    
        // set our namespaces to make everything pretty
        model.setNsPrefix("foaf", FOAF.NS);
        model.setNsPrefix("rdfs", RDFS.getURI());
        model.setNsPrefix("foo", "http://example.com/foo#");
    
        // output our result to output.ttl
        model.write(new FileOutputStream("output.ttl"), "TTL");
    
    
    }
    

相关问题