You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT转换XML生成RDF时XPATH失效,<exam:Cabecalho>节点为空求助

问题分析与解决方案

看起来你的XSLT代码里有几个关键的XPath和模板匹配问题,导致转换结果不符合预期,下面逐一拆解:

1. <exam:Cabecalho>节点为空的原因

这是模板匹配路径的核心问题!你的模板写的是:

<xsl:template match="documento/cabecalho">
  <dc:title>
    <xsl:value-of select="titulo" />
  </dc:title>
</xsl:template>

而在根模板里调用<xsl:apply-templates select="documento/cabecalho" />时,你选中的是/documento/cabecalho节点。虽然match="documento/cabecalho"看起来是匹配这个节点,但某些XSLT处理器对这种相对路径的匹配模式会有歧义,更稳妥的方式是使用绝对路径明确指定要匹配的节点:

<xsl:template match="/documento/cabecalho">
  <dc:title>
    <xsl:value-of select="titulo" />
  </dc:title>
</xsl:template>

或者简化成直接匹配cabecalho节点(如果你的XML里不会有其他同名节点):

<xsl:template match="cabecalho">
  <dc:title>
    <xsl:value-of select="titulo" />
  </dc:title>
</xsl:template>

这样apply-templates就能正确找到模板并输出<dc:title>内容了。

2. rdf:about属性值为空的原因

你在属性值模板里用了{documento/cabecalho/titulo/text()},虽然在根节点上下文里这个路径逻辑上正确,但text()会返回文本节点集合,某些处理器在处理属性值时如果遇到空节点集会返回空字符串。更稳妥的写法是直接取元素的字符串值(不需要显式调用text()),同时使用绝对路径避免上下文混淆:

<rdf:Description rdf:about="{/documento/cabecalho/titulo}">

这样就能正确获取titulo的文本内容作为rdf:about的值了。

3. rdf:type错误指向documento的原因

这一点非常奇怪,因为你的原XSLT里明确写的是<rdf:type rdf:resource="Livro" />,但转换结果里变成了documento。可能的情况包括:

  • 你误粘贴了错误的转换结果;
  • 实际运行的XSLT文件被修改过;
  • XSLT处理器出现了异常。

另外,注意Livro是相对URI,结合xml:base="http://example.com/",它的完整URI是http://example.com/Livro,如果你想更明确,可以写成<rdf:type rdf:resource="#Livro" />(如果类定义在同一个文档里)或者完整URI,但原写法本身是没问题的。

额外的RDF规范问题

你的XSLT里把Indice同时定义为类和属性:

<rdfs:Class rdf:about="Indice" />
<rdfs:Property rdf:about="Indice">

这会导致同一个URI(http://example.com/Indice)既是类又是属性,不符合RDF的语义规范,建议把属性名改成hasIndice或者其他区分开的名称,避免冲突。


修正后的XSLT大致如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" > ]>
<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:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:exam="http://example.com/">
<xsl:template match="/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xml:base="http://example.com/" xmlns:exam="http://example.com/">
<rdfs:Class rdf:about="Livro">
<rdfs:subClassOf rdf:resource="Cabecalho" />
<rdfs:subClassOf rdf:resource="Parte" />
<rdfs:subClassOf rdf:resource="Seccao" />
<rdfs:subClassOf rdf:resource="Subseccao" />
<rdfs:subClassOf rdf:resource="Receita" />
</rdfs:Class>
<rdfs:Class rdf:about="Cabecalho" />
<rdfs:Class rdf:about="Parte">
<rdfs:subClassOf rdf:resource="Indice" />
</rdfs:Class>
<rdfs:Class rdf:about="Seccao">
<rdfs:subClassOf rdf:resource="Indice" />
<rdfs:subClassOf rdf:resource="Parte" />
</rdfs:Class>
<rdfs:Class rdf:about="Subseccao">
<rdfs:subClassOf rdf:resource="Indice" />
<rdfs:subClassOf rdf:resource="Parte" />
<rdfs:subClassOf rdf:resource="Seccao" />
</rdfs:Class>
<rdfs:Class rdf:about="Receita">
<rdfs:subClassOf rdf:resource="Indice" />
<rdfs:subClassOf rdf:resource="Parte" />
<rdfs:subClassOf rdf:resource="Seccao" />
<rdfs:subClassOf rdf:resource="Subseccao" />
</rdfs:Class>
<rdfs:Property rdf:about="nome">
<rdfs:domain rdf:resource="Livro" />
<rdfs:range rdf:resource="&rdfs;Literal" />
</rdfs:Property>
<rdfs:Property rdf:about="hasIndice">
<rdfs:domain rdf:resource="Livro" />
<rdfs:range rdf:resource="Livro" />
</rdfs:Property>
<rdf:Description rdf:about="{/documento/cabecalho/titulo}">
<rdf:type rdf:resource="Livro" />
<exam:Cabecalho>
<xsl:apply-templates select="/documento/cabecalho" />
</exam:Cabecalho>
</rdf:Description>
</rdf:RDF>
</xsl:template>
<xsl:template match="/documento/cabecalho">
<dc:title>
<xsl:value-of select="titulo" />
</dc:title>
</xsl:template>
</xsl:stylesheet>

内容的提问来源于stack exchange,提问作者Rui Pedro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:58:29