适配SPARQL动态变量的XSLT导入规则集开发求助
动态SPARQL结果转结构化XML的XSLT解决方案
需求说明
需要构建XSLT处理SPARQL返回的XML:
- 提取
<head>中的<variable>作为列名(Row元素的属性名) - 每个
<result>对应一个<Row>元素,将<binding>中的数据填充到对应属性中 - 支持动态变量数量,无需硬编码变量名
源SPARQL XML片段
<?xml version='1.0' encoding='UTF-8'?> <sparql xmlns='http://www.w3.org/2005/sparql-results#'> <head> <variable name='naam'/> <variable name='description'/> <variable name='uri'/> </head> <results> <result> <binding name='naam'> <literal>Zweepmast, thermisch verzinken</literal> </binding> <binding name='description'> <literal>Een zweepmast (uithoudercombinatie) dient thermisch te worden verzinkt volgens NEN-EN-ISO 1461 en vervolgens voorzien van een 2-laags natlak-of poedercoating, dit ter keuze van de fabrikant.</literal> </binding> <binding name='uri'> <uri>http://data.provincie-zuidholland.nl/id/62ac71da-b59e-ec11-b683-001dd8d70289</uri> </binding> </result> <result> <binding name='naam'> <literal>Verkeerskundige draagconstructie, afmetingen van grondstuk</literal> </binding> <binding name='description'> <literal>Een staander van een portaal of een gecombineerde lichtmast dient te worden voorzien van een grondstuk met een lengte van 2.000 mm. Het grondstuk is voorzien van minimaal twee grondvleugels met een minimaal formaat van 640 x 180 x 6 mm per grondvleugel. Het gebruik van demontabele grondvleugels of betonplaten is niet toegestaan.</literal> </binding> <binding name='uri'> <uri>http://data.provincie-zuidholland.nl/id/099f3e6f-b99e-ec11-b683-001dd8d70289</uri> </binding> </result> </results> </sparql>
现有XSLT问题
原XSLT硬编码了属性名,且使用了不被支持的current-group()函数,无法处理动态变量:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/results"> <Import> <!-- This part is used to import all details for specifications that have a verification plan--> <xsl:for-each select="result/binding"> <Row> <!-- Name--> <xsl:attribute name="naam"><xsl:value-of select="current-group()[1]/literal/text()"/></xsl:attribute> <!-- Description --> <xsl:attribute name="description"><xsl:value-of select="current-group()[1]/literal/text()"/></xsl:attribute> <!-- uri --> <xsl:attribute name="uri"><xsl:value-of select="current-group()[1]/uri/text()" /></xsl:attribute> </Row> </xsl:for-each> </Import> </xsl:template> </xsl:stylesheet>
解决方案XSLT
以下XSLT完全支持动态变量,无需硬编码,且不依赖current-group():
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sparql="http://www.w3.org/2005/sparql-results#" version="2.0"> <xsl:output method="xml" indent="yes"/> <!-- 匹配SPARQL根节点 --> <xsl:template match="/sparql"> <Import> <!-- 提取所有变量名,用于动态生成属性 --> <xsl:variable name="variables" select="sparql:head/sparql:variable/@name"/> <!-- 遍历每个结果行 --> <xsl:for-each select="sparql:results/sparql:result"> <Row> <!-- 为每个变量生成对应的属性,填充绑定值 --> <xsl:for-each select="$variables"> <xsl:attribute name="{.}"> <!-- 取当前result下对应变量名的binding的文本内容(兼容literal/uri等节点类型) --> <xsl:value-of select="../sparql:binding[@name = current()]/node()/text()"/> </xsl:attribute> </xsl:for-each> </Row> </xsl:for-each> </Import> </xsl:template> </xsl:stylesheet>
核心说明
- 命名空间处理:必须声明SPARQL命名空间,否则无法正确匹配源XML中的节点
- 动态变量获取:通过
$variables变量存储所有<variable>的name属性,实现完全动态的属性生成 - 取值逻辑:对每个
<result>,遍历变量列表,通过[@name = current()]定位对应的<binding>,用node()/text()获取所有子节点的文本(兼容<literal>、<uri>等不同类型的绑定值) - 替代current-group:无需分组操作,直接通过相对路径和属性匹配定位数据,避免依赖分组函数
内容的提问来源于stack exchange,提问作者Xanthouse
相关产品推荐
相关产品推荐

