-1

[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の場合もあります。

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.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.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.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>

これらの例は構造の簡略化されたバージョンですが、原理を示す必要があります。3つの例すべてで同じ出力を生成するXSLTソートを実装したいと思います。変換された結果がバージョン1、2、または3(またはその他の順序)のように見えるかどうかはそれほど重要ではありません。

4

2 に答える 2

0

ノード名が同じでテキストの内容が同じである場合、ソートの目的で、2つのノードが等しいと想定しています。私が理解しているように、入力ドキュメントは何らかの決定論的な方法でソートする必要がありますが、決定論的である限り、ソートが何であるかは問題ではありません。したがって、ノード名と直接のテキストの子の組み合わせで並べ替えることをお勧めします。ハッシュは必要ありません。

このスタイルシートを試してください:

<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="@*" />
          <xsl:apply-templates select="node()">
            <xsl:sort select="namespace-uri()" data-type="text" />
            <xsl:sort select="local-name()" data-type="text"/>
            <xsl:sort select="string-join(./text(),' ')" data-type="text"/>
          </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
于 2012-06-20T13:49:47.793 に答える
0

結局、Javaでソートを実装することになりました。

基本的に、私はDOMを子から再帰的にソートします。

private Element sort(Element e) {
    // first, sort children's contents recursively
    List<Element> elementNodes = removeElementChildNodes(e);
    for (Element child: elementNodes) {
        sort(child);
    }
    // after that, sort the order of these children
    List<Element> sortedElementNodes = sortElements(elementNodes);
    // add them back
    for (Element child: sortedElementNodes) {
        e.appendChild(child);
    }
    return e;
}

実際の並べ替えでは、最初に要素名といくつかの重要な属性名を比較し、それらがすべて等しい場合は、ノードとその子の正規化された文字列変換を比較します(子のコンテンツはこの時点ですでに並べ替えられていることが保証されます)

private class ElementSortingComparator implements Comparator<Element> {

    public int compare(Element o1, Element o2) {
        CompareToBuilder c = new CompareToBuilder(); 
        c.append(o1.getTagName(), o2.getTagName());
        c.append(o1.getAttribute(ID_ATTRIBUTE),
                o2.getAttribute(ID_ATTRIBUTE));
        c.append(o1.getAttribute(ABOUT_ATTRIBUTE),
                o2.getAttribute(ABOUT_ATTRIBUTE));
        int result = c.toComparison();
        if (result == 0) {
            String node1 = partialNodeToString(o1);
            String node2 = partialNodeToString(o2);
            result = node1.compareTo(node2);
        }
        return result;
    }
}
于 2012-06-26T08:05:12.307 に答える