帮助通过XSL将RDF转换为HTML

时间:2011-01-03 11:27:30

标签: html xml xslt

我有从服务中获得的xml / rdf文件。所以,我需要通过XSL将其转换为html块。

以下是xml / rdf文件的一部分:

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:c="http://s.opencalais.com/1/pred/">
    <rdf:Description rdf:about="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d/Instance/2">
        <rdf:type rdf:resource="http://s.opencalais.com/1/type/sys/InstanceInfo"/>
        <c:docId rdf:resource="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d"/>
        <c:subject rdf:resource="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5"/><!--Company: Zila Inc.; -->
        <c:detection>[                PHOENIX, March 28 /PRNewswire/ -- ]Zila, Inc.[ (Nasdaq: ZILA) Chairman and President Joseph]</c:detection>
        <c:prefix>                PHOENIX, March 28 /PRNewswire/ -- </c:prefix>
        <c:exact>Zila, Inc.</c:exact>
        <c:suffix> (Nasdaq: ZILA) Chairman and President Joseph</c:suffix>
        <c:offset>131</c:offset>
        <c:length>10</c:length>
    </rdf:Description>
    <rdf:Description rdf:about="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d/Instance/3">
        <rdf:type rdf:resource="http://s.opencalais.com/1/type/sys/InstanceInfo"/>
        <c:docId rdf:resource="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d"/>
        <c:subject rdf:resource="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5"/><!--Company: Zila Inc.; -->
        <c:detection>[March 28 /PRNewswire/ -- Zila, Inc. (Nasdaq: ]ZILA[) Chairman and President Joseph Hines announced]</c:detection>
        <c:prefix>March 28 /PRNewswire/ -- Zila, Inc. (Nasdaq: </c:prefix>
        <c:exact>ZILA</c:exact>
        <c:suffix>) Chairman and President Joseph Hines announced</c:suffix>
        <c:offset>151</c:offset>
        <c:length>4</c:length>
    </rdf:Description>
    <rdf:Description rdf:about="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5">
        <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Company"/>
        <c:name>Zila Inc.</c:name>
        <c:nationality>N/A</c:nationality>
    </rdf:Description>
    <rdf:Description rdf:about="http://d.opencalais.com/pershash-1/31337438-fcbd-3137-9705-ef2f1a752b88">
        <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Person"/>
        <c:name>Joseph Hines</c:name>
        <c:persontype>economic</c:persontype>
        <c:nationality>N/A</c:nationality>
        <c:commonname>Joseph Hines</c:commonname>
    </rdf:Description>
    ...
</rdf:RDF>

所以,我必须从中构建html。 Html由实体列表组成,它们具有标题和项目。

标题是<rdf:type>节点属性中的最后一个单词。 Expamle:

<rdf:Description rdf:about="http://d.opencalais.com/pershash-1/31337438-fcbd-3137-9705-ef2f1a752b88">
            <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Person"/>
            <c:name>Joseph Hines</c:name>
            <c:persontype>economic</c:persontype>
            <c:nationality>N/A</c:nationality>
            <c:commonname>Joseph Hines</c:commonname>
        </rdf:Description>

此节点必须转换为

<div class="Block">
    <div class="Header Person">Person</div>
    <div class="Item">Joseph Hines</div> 
</div>

所以,我有很多这样的块,它们在<c:name>节点中有Person(或另一个)Header和Item。

如何将此xml / rdf转换为html块并将具有相同标题(例如Person)的所有项目放在同一个块中?

看起来应该是

<div class="Block">
    <div class="Header Person">Person</div>
    <div class="Item">Joseph Hines</div> 
    <div class="Item">another item</div>
    ...
</div>
<div class="Block">
    <div class="Header Company">Company</div>
    <div class="Item">Zila Inc.</div> 
    <div class="Item">another company item</div>
    ...
</div>
...

抱歉,如果问题不明确。我会回答所有问题,以帮助理解我的问题。

提前致谢。

2 个答案:

答案 0 :(得分:2)

这个XSLT:

<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
            xmlns:c="http://s.opencalais.com/1/pred/"
            exclude-result-prefixes="rdf c">
<xsl:output method="html" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="entityByType" match="rdf:Description" use="substring-after(rdf:type/@rdf:resource, 'type/em/e/')"/>

<xsl:template match="/*">
    <xsl:apply-templates select="key('entityByType', 'Person')[1]"/>
    <xsl:apply-templates select="key('entityByType', 'Company')[1]"/>
</xsl:template>

<xsl:template match="rdf:Description">
    <div class="block">
        <xsl:variable name="entityType" select="substring-after(rdf:type/@rdf:resource, 'type/em/e/')"/>
        <div class="header {$entityType}">
            <xsl:value-of select="$entityType"/>
        </div>
        <xsl:apply-templates select="key('entityByType', $entityType)" mode="inner-content"/>
    </div>
</xsl:template>

<xsl:template match="rdf:Description" mode="inner-content">
    <div class="item">
        <xsl:value-of select="c:name"/>
    </div>
</xsl:template>

</xsl:stylesheet>

应用于更具描述性的输入XML:

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:c="http://s.opencalais.com/1/pred/">
<rdf:Description rdf:about="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d/Instance/2">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/sys/InstanceInfo"/>
    <c:docId rdf:resource="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d"/>
    <c:subject rdf:resource="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5"/><!--Company: Zila Inc.; -->
    <c:detection>[                PHOENIX, March 28 /PRNewswire/ -- ]Zila, Inc.[ (Nasdaq: ZILA) Chairman and President Joseph]</c:detection>
    <c:prefix>                PHOENIX, March 28 /PRNewswire/ -- </c:prefix>
    <c:exact>Zila, Inc.</c:exact>
    <c:suffix> (Nasdaq: ZILA) Chairman and President Joseph</c:suffix>
    <c:offset>131</c:offset>
    <c:length>10</c:length>
</rdf:Description>
<rdf:Description rdf:about="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d/Instance/3">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/sys/InstanceInfo"/>
    <c:docId rdf:resource="http://d.opencalais.com/dochash-1/f1a1cace-8df1-3247-b8e2-331a8fa8363d"/>
    <c:subject rdf:resource="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5"/><!--Company: Zila Inc.; -->
    <c:detection>[March 28 /PRNewswire/ -- Zila, Inc. (Nasdaq: ]ZILA[) Chairman and President Joseph Hines announced]</c:detection>
    <c:prefix>March 28 /PRNewswire/ -- Zila, Inc. (Nasdaq: </c:prefix>
    <c:exact>ZILA</c:exact>
    <c:suffix>) Chairman and President Joseph Hines announced</c:suffix>
    <c:offset>151</c:offset>
    <c:length>4</c:length>
</rdf:Description>
<rdf:Description rdf:about="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Company"/>
    <c:name>Zila Inc.1</c:name>
    <c:nationality>N/A</c:nationality>
</rdf:Description>
<rdf:Description rdf:about="http://d.opencalais.com/pershash-1/31337438-fcbd-3137-9705-ef2f1a752b88">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Person"/>
    <c:name>Joseph Hines1</c:name>
    <c:persontype>economic</c:persontype>
    <c:nationality>N/A</c:nationality>
    <c:commonname>Joseph Hines</c:commonname>
</rdf:Description>
<rdf:Description rdf:about="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Company"/>
    <c:name>Zila Inc.2</c:name>
    <c:nationality>N/A</c:nationality>
</rdf:Description>
<rdf:Description rdf:about="http://d.opencalais.com/pershash-1/31337438-fcbd-3137-9705-ef2f1a752b88">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Person"/>
    <c:name>Joseph Hines2</c:name>
    <c:persontype>economic</c:persontype>
    <c:nationality>N/A</c:nationality>
    <c:commonname>Joseph Hines</c:commonname>
</rdf:Description>
<rdf:Description rdf:about="http://d.opencalais.com/comphash-1/f69211ed-b366-31a8-9e04-b85c50b8e0a5">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Company"/>
    <c:name>Zila Inc.3</c:name>
    <c:nationality>N/A</c:nationality>
</rdf:Description>
<rdf:Description rdf:about="http://d.opencalais.com/pershash-1/31337438-fcbd-3137-9705-ef2f1a752b88">
    <rdf:type rdf:resource="http://s.opencalais.com/1/type/em/e/Person"/>
    <c:name>Joseph Hines3</c:name>
    <c:persontype>economic</c:persontype>
    <c:nationality>N/A</c:nationality>
    <c:commonname>Joseph Hines</c:commonname>
</rdf:Description>
</rdf:RDF>

产生正确的结果:

<div class="block">
    <div class="header Person">Person</div>
    <div class="item">Joseph Hines1</div>
    <div class="item">Joseph Hines2</div>
    <div class="item">Joseph Hines3</div>
</div>
<div class="block">
    <div class="header Company">Company</div>
    <div class="item">Zila Inc.1</div>
    <div class="item">Zila Inc.2</div>
    <div class="item">Zila Inc.3</div>
</div>

修改

<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
            xmlns:c="http://s.opencalais.com/1/pred/"
            exclude-result-prefixes="rdf c">
<xsl:output method="html" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="entityByType" match="rdf:Description" use="substring-after(rdf:type/@rdf:resource, 'type/em/e/')"/>

<xsl:template match="/*">
    <xsl:apply-templates select="
    rdf:Description[
    generate-id() = generate-id(key('entityByType', substring-after(rdf:type/@rdf:resource, 'type/em/e/')))
    ]"/>
</xsl:template>

<xsl:template match="rdf:Description">
    <div class="block">
        <xsl:variable name="entityType">
            <xsl:call-template name="substring-after-last">
                <xsl:with-param name="input" select="rdf:type/@rdf:resource"/>
                <xsl:with-param name="substr" select="'/'"/>
            </xsl:call-template>
        </xsl:variable>
        <div class="header {$entityType}">
            <xsl:value-of select="$entityType"/>
        </div>
        <xsl:apply-templates select="key('entityByType', $entityType)" mode="inner-content"/>
    </div>
</xsl:template>

<xsl:template match="rdf:Description" mode="inner-content">
    <div class="item">
        <xsl:value-of select="c:name"/>
    </div>
</xsl:template>

<xsl:template name="substring-after-last">
    <xsl:param name="input"/>
    <xsl:param name="substr"/>
    <xsl:variable name="temp" select="substring-after($input,$substr)"/>
    <xsl:choose>
        <xsl:when test="$substr and contains($temp,$substr)">
            <xsl:call-template name="substring-after-last">
            <xsl:with-param name="input"  select="$temp" />
            <xsl:with-param name="substr" select="$substr" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$temp"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

结果:

<div class="block">
    <div class="header InstanceInfo">InstanceInfo</div>
</div>
<div class="block">
    <div class="header Company">Company</div>
    <div class="item">Zila Inc.1</div>
    <div class="item">Zila Inc.2</div>
    <div class="item">Zila Inc.3</div>
</div>
<div class="block">
    <div class="header Person">Person</div>
    <div class="item">Joseph Hines1</div>
    <div class="item">Joseph Hines2</div>
    <div class="item">Joseph Hines3</div>
</div>

您可以自行排除任何不必要的类型,也可以为此类排除提供标准。

答案 1 :(得分:1)

这是一个XSLT 2.0样式表,可以使用Saxon 9或AltovaXML Tools等XSLT 2.0处理器运行:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:c="http://s.opencalais.com/1/pred/"
  exclude-result-prefixes="rdf c"
  version="2.0">

  <xsl:output method="html" indent="yes"/>

  <xsl:template match="rdf:RDF">
    <xsl:for-each-group select="rdf:Description[rdf:type/@rdf:resource]"
      group-by="tokenize(rdf:type/@rdf:resource, '/')[last()]">

      <div class="Block">
        <div class="Header {current-grouping-key()}">
          <xsl:value-of select="current-grouping-key()"/>
        </div>
        <xsl:apply-templates select="current-group()/c:name"/>
      </div>
    </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="c:name">
    <div class="Item">
      <xsl:value-of select="."/>
    </div>
  </xsl:template>

</xsl:stylesheet>