【发布时间】:2012-06-20 12:00:25
【问题描述】:
我想在我的 [OWL] (http://www.w3.org/TR/owl-ref/) 文件中引入确定性排序,以便我可以将修改后的文件与原始文件进行比较并更轻松地查看它的位置已经变了。该文件由工具(Protege)生成,元素的顺序是半随机变化的。
问题是排序不能基于简单的事情,比如给定元素的名称和属性。通常差异只出现在下面几级的子节点中。
例子:
<owl:Class rdf:about="#SomeFooClass">
<rdfs:subClassOf><!-- subclass definition 1 -->
<owl:Restriction>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
<owl:onProperty>
<owl:DatatypeProperty rdf:ID="negate"/>
</owl:onProperty>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf><!-- subclass definition 2 -->
<owl:Restriction>
<owl:onProperty>
<owl:DatatypeProperty rdf:about="#name"/>
</owl:onProperty>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
</owl:Restriction>
</rdfs:subClassOf>
这里的子类定义 1 和 2(以及其中的其他子元素)按顺序变化,有时 1 是第一个,有时是 2。
我基于一些常见的直接属性(例如 s about 和 ID)实现了排序,虽然这修复了许多模棱两可的排序,但它无法解决这个问题。 XSLT:
<xsl:stylesheet version="2.0"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()">
<xsl:sort select="@rdf:about" data-type="text"/>
<xsl:sort select="@rdf:ID" data-type="text"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我在想,也许解决方案需要能够为每个元素计算某种“哈希码”,这会考虑到它的子元素的所有内容。这样子类定义 1 的哈希码为 3487631,子类定义 2 的哈希码为 45612,它们之间的排序是确定性的(如果它们的子元素未修改)。
编辑:刚刚意识到哈希码计算不应该关心子注释排序来实现它想要做的事情。
我可以主要使用直接已知的属性值,然后使用哈希码,如果它们相等的话。我可能会得到类似的结果:
<xsl:stylesheet version="2.0"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()">
<xsl:sort select="@rdf:about" data-type="text"/>
<xsl:sort select="@rdf:ID" data-type="text"/>
<xsl:sort select="my:hashCode(.)" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:function name="my:hashCode" as="xs:string">
...
</xsl:function>
</xsl:stylesheet>
但不知道如何实现 my:hashCode。
编辑:根据要求,举几个例子。该工具在保存相同数据时可能或多或少随机产生例如以下类型的结果 (1-3):
1.
<owl:Class rdf:about="#SomeFooClass">
<rdfs:subClassOf><!-- subclass definition 1 -->
<owl:Restriction>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
<owl:onProperty>
<owl:DatatypeProperty rdf:ID="negate"/>
</owl:onProperty>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf><!-- subclass definition 2 -->
<owl:Restriction>
<owl:onProperty>
<owl:DatatypeProperty rdf:about="#name"/>
</owl:onProperty>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
2.
<owl:Class rdf:about="#SomeFooClass">
<rdfs:subClassOf><!-- subclass definition 2 -->
<owl:Restriction>
<owl:onProperty>
<owl:DatatypeProperty rdf:about="#name"/>
</owl:onProperty>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf><!-- subclass definition 1 -->
<owl:Restriction>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
<owl:onProperty>
<owl:DatatypeProperty rdf:ID="negate"/>
</owl:onProperty>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
3.
<owl:Class rdf:about="#SomeFooClass">
<rdfs:subClassOf><!-- subclass definition 2 -->
<owl:Restriction>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
<owl:onProperty>
<owl:DatatypeProperty rdf:about="#name"/>
</owl:onProperty>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf><!-- subclass definition 1 -->
<owl:Restriction>
<owl:onProperty>
<owl:DatatypeProperty rdf:ID="negate"/>
</owl:onProperty>
<owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:maxCardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
这些示例是结构的简化版本,但应该显示原理。我想实现一个 XSLT 排序,它将为所有 3 个示例产生相同的输出。转换后的结果看起来像版本 1、2 还是 3(或其他排序)并不那么重要。
【问题讨论】:
-
感谢哈希计算参考。当我编辑我的 OP 时,我认为简单的哈希计算是行不通的。这是因为我有这样的案例
-
我不明白。你的问题说你想要一个散列函数,但你的 cmets 说你不想要一个散列函数。
-
哈希计算只是一个潜在解决方案的快速想法。我想要的是对我的数据进行确定性排序。不知道是否可以通过某种排序前的哈希计算来改进它?或者如果我可以让 XSLT 从叶节点开始排序?这种方式哈希总是基于具有确定顺序的元素计算。