3

schematron を使用してインスタンス ドキュメントを検証しようとしていますが、Java XSLT プロセッサの実装に問題があります。スキーマトロンから XSL を生成しようとすると、単純なものであっても、予想とは異なる結果が得られます。

xsltproc (cygwin) を使用して変換を行う場合、すべて問題ありません。しかし、Saxon-B 9.1.0.8、デフォルトの Java 1.6 実装、または Saxon-PE 9.3.0.5 での Oxygen IDE の XSLT デバッガーを使用すると、無効な XSL ファイルが生成されます。原因は、名前空間がどこにも宣言されていないプレフィックスを含む要素のextension-element-prefixes属性です。このようなスタイルシートは、使用すると必ず失敗します。xsl:stylesheetexsl

スキーマトロンは実行時にアプリケーションで生成されるため、生成されたファイルを手動で編集することは問題外です。私は何か間違ったことをしなければなりませんよね?問題を に追跡しましたiso_schematron_skeleton_for_saxon.xsl(またはiso_schematron_skeleton_for_xslt1.xsl、使用されている実装によっては、はい、両方を試してみましたが、最終結果は同じでした)。スケルトンは名前空間が欠落している適切なスタイルシートを明確に作成しますが、後でどういうわけか魔法のように削除されます。私は XSLT の専門家ではないので、ここで何が間違っているのかわかりません。私がどこかで見逃したばかげたものだと確信しています。以下の入力の出力が異なる理由を知りたいです。

これは、いくつかの名前空間を定義するだけのサンプル スキーマトロンです (これが有効なスキーマと見なされることを願っています)。

<?xml version="1.0" encoding="utf-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" 
    queryBinding="exslt">
   <sch:ns uri="http://exslt.org/dynamic" prefix="dyn"/>
   <sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0" 
      xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1" 
      uri="urn:ietf:params:xml:ns:yang:ietf-inet-types" 
      prefix="inet"/>
   <sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0" 
      xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1" 
      uri="urn:ietf:params:xml:ns:yang:ietf-ipfix-psamp" 
      prefix="ipfix"/>
   <sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0" 
      xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1" 
      uri="urn:ietf:params:xml:ns:yang:ietf-yang-types" 
      prefix="yang"/>
   <sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0" 
      xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1" 
      uri="urn:ietf:params:xml:ns:netconf:base:1.0" 
      prefix="nc"/>   
</sch:schema>

Java XSLT プロセッサから取得したスニペットを次に示します (これは Oxygen からのものです。xslt1 または xslt2 の iso が使用されているかどうかは関係ありません。問題は解決しません)。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--This XSLT was automatically generated from a Schematron schema.-->
<xsl:stylesheet xmlns:sch="http://www.ascc.net/xml/schematron" 
    xmlns:set="http://exslt.org/sets"
    xmlns:str="http://exslt.org/strings"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:date="http://exslt.org/dates-and-times"
    xmlns:dyn="http://exslt.org/dynamic"
    xmlns:iso="http://purl.oclc.org/dsdl/schematron"
    xmlns:math="http://exslt.org/math"
    xmlns:random="http://exslt.org/random"
    xmlns:regexp="http://exslt.org/regular-expressions"
    xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types"
    xmlns:ipfix="urn:ietf:params:xml:ns:yang:ietf-ipfix-psamp"
    xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types"
    xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
    extension-element-prefixes="date dyn exsl math random regexp set str"
    version="1.0">
    <!--Removed in favor of brevity.-->
</xsl:stylesheet>

xsltproc が生成するものと、Java にも生成してほしいものは次のとおりです。

<?xml version="1.0" standalone="yes"?>
<!--This XSLT was automatically generated from a Schematron schema.-->
<axsl:stylesheet 
    xmlns:date="http://exslt.org/dates-and-times" 
    xmlns:dyn="http://exslt.org/dynamic" 
    xmlns:exsl="http://exslt.org/common" 
    xmlns:math="http://exslt.org/math" 
    xmlns:random="http://exslt.org/random" 
    xmlns:regexp="http://exslt.org/regular-expressions" 
    xmlns:set="http://exslt.org/sets" 
    xmlns:str="http://exslt.org/strings" 
    xmlns:axsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:sch="http://www.ascc.net/xml/schematron" 
    xmlns:iso="http://purl.oclc.org/dsdl/schematron" 
    xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types" 
    xmlns:ipfix="urn:ietf:params:xml:ns:yang:ietf-ipfix-psamp" 
    xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types" 
    xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" 
    extension-element-prefixes="date dyn exsl math random regexp set str" 
    version="1.0">
    <!--Removed in favor of brevity.-->
</axsl:stylesheet>

ご覧のとおり、Java 出力には、対応するプレフィックスの exsl 名前空間がありません。名前空間を処理することになっている iso スケルトンの部分に実験的なフラグが立てられていることに気付きました.必要に応じて、これを機能させるために汚いハックを適用するつもりです (schematron を詳細に学習していないために恥ずかしいことを尋ねている場合を除きます)。 )。何か案は?

編集: Martin が以下のコメントで提案したように、純粋な XSLT 1.0 プロセッサを使用してみました。xalan (コンパイル済みバージョンと解釈バージョンの両方) と saxon 6.5.5 を使用しました。どちらの xalans も exsl 名前空間を追加しません。Saxon は、「属性が追加された後に名前空間を追加できません」などのエラーでスキーマトロンの処理に失敗することさえあります (xslt1 の iso スケルトンの 1534 行目)。queryBinding="exslt" でスキーマトロンを変換できる唯一のプロセッサは xsltproc のままです。また、私が試した唯一の非 Java プロセッサでもあります。問題のある XSL を少し読んだ後、変換が saxon9 でテストされているという主張が行われているコメントに気付きました。したがって、これは機能する必要があります。

PS: 長い投稿で申し訳ありませんが、この例を示すことが重要だと思います。

4

1 に答える 1

4

XSLT の知識が不足しているにもかかわらず、自分でデバッグしてこの問題を解決しました。このソリューションは、 Xalan (インタープリタ バージョン、xalan.jar またはより正確にorg.apache.xalan.processor.TransformerFactoryImplは ) を選択した Java XSLT プロセッサとして使用することに重点を置いています。この解決策では、schematron スケルトンに変更を加え、移植不可にする必要があります。

問題のある XSL コードの部分を分離した後iso_schematron_skeleton_for_xslt1.xsl、「http://exslt.org/common」名前空間が変換によって生成されるはずだったスタイルシートから単純に消えてしまう原因を突き止めました (スケルトンはメタつまり、出力もスタイルシートです)。生成と生成されたスタイルシートの両方がその EXSLT 名前空間の関数を使用し、単一の XSL ファイル内の 2 つの xsl:stylesheet 要素でそれを指定すると、すべての Java XSLT プロセッサが爆発するようです。真剣に。これを行うと (以下の例を参照)、生成されたスタイルシートの名前空間は単純に消えます。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"
 xmlns:exsl="http://exslt.org/common"
 extension-element-prefixes="exsl">
    <xsl:output method="xml" omit-xml-declaration="yes" />
    <xsl:strip-space elements="*"/>
    <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

    <xsl:template match="/">
        <xsl:call-template name="disappearance-act" />
    </xsl:template>

    <xsl:template name="disappearance-act">
        <axsl:stylesheet
        xmlns:exsl="http://exslt.org/common"
        extension-element-prefixes="exsl" >
            <xsl:attribute name="version">1.0</xsl:attribute>
        </axsl:stylesheet>
    </xsl:template>
</xsl:stylesheet>

したがって、スキーマトロンを Java を使用して XSL に変換する場合は、これを避ける必要があります。handle-namespace テンプレートで名前空間属性を構築するために使用される exsl:node-set 関数のために、スケルトンは単一の場所でのみ EXSLT を使用するため、このテンプレートを外部スタイルシートに移動してから含めることで、この問題を回避しました。スケルトンで。消える名前空間が生成された xsl:stylesheet 要素に対してのみ指定されている場合、問題は単純に解消されます。なぜこれが起こっているのか...私にはまったくわかりません。おそらく、XSLT に詳しい人なら、この質問に答えることができるでしょう。

次に (いいえ、まだ完了していません)、どこかのテストで function-available('exsl:node-set')" を使用すると、Xalan にバグがあるように見えるという事実に注意する必要があります (これはまさにこの関数は非常に明確に実装され、Xalan によってサポートされていますが、テストは false を返します。したがって、これを使用しないでください。単純にこの関数が存在すると仮定し、 handle-namespace テンプレート (これにより、そのテンプレートの他のすべての xsl:choose ブランチも冗長になるため、単純にそれらも削除しました。以下に、質問からサンプル スキーマを適切に変換するために行ったすべての変更を示します。生成されたスタイルシートに他の問題があるかどうかはわかりません.これは私の質問の問題を解決するだけです.

私が変更したスキーマトロン スケルトン xsl の一部:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"
 xmlns:sch="http://www.ascc.net/xml/schematron"
 xmlns:iso="http://purl.oclc.org/dsdl/schematron" >
     <!--Removed no longer neccessary stuff from root stylesheet-->
    <xsl:output method="xml" omit-xml-declaration="no" standalone="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

     <!--This was added.-->
    <xsl:include href="namespaces.xsl"/>

    <xsl:template match="/">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="iso:schema[@queryBinding='exslt']">
        <axsl:stylesheet
        xmlns:date="http://exslt.org/dates-and-times"
        xmlns:dyn="http://exslt.org/dynamic"
        xmlns:exsl="http://exslt.org/common"
        xmlns:math="http://exslt.org/math"
        xmlns:random="http://exslt.org/random"
        xmlns:regexp="http://exslt.org/regular-expressions"
        xmlns:set="http://exslt.org/sets"
        xmlns:str="http://exslt.org/strings"
        extension-element-prefixes="date dyn exsl math random regexp set str" >

            <xsl:apply-templates select="iso:ns"/>
            <xsl:attribute name="version">1.0</xsl:attribute>
     <!--Irrelevant changes here in order to make this stylesheet runnable.-->
        </axsl:stylesheet>
    </xsl:template>

    <xsl:template match="iso:ns">
        <xsl:call-template name="handle-namespace" />
    </xsl:template>

    <!--handle-namespace template was removed here-->

</xsl:stylesheet>

インクルード ファイルの内容は次のとおりです。

<!--namespaces.xsl-->
<!--The include stylesheet which handles the namespaces from schematron.-->
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:exsl="http://exslt.org/common"
 extension-element-prefixes="exsl">

    <xsl:template name="handle-namespace">
        <xsl:variable name="ns-dummy-elements">
            <xsl:element name="{@prefix}:dummy" namespace="{@uri}"/>
        </xsl:variable>
        <xsl:variable name="p" select="@prefix"/>
        <xsl:copy-of select="exsl:node-set($ns-dummy-elements)
                                  /*/namespace::*[local-name()=$p]"/>
    </xsl:template>

</xsl:stylesheet>

これは、私の問題の回避策を提供するだけです。これは私の質問に対する完全な回答とは考えていないため、名前空間が消えている理由を誰かが説明するまで、回答済みとしてマークしません。

編集: xalan -j メーリング リストに質問を投稿し、これ (EXSLT) を読んだ後、消滅する名前空間が実際に起こるべきことであるという結論に達しました。extension-element-prefixes 属性は、拡張名前空間が結果ツリーに出力されないようにするために使用されます。xsltproc が XSLT 1.0 仕様に準拠していないことが再びわかりました。これは、iso schematron スケルトンにバグがあることも意味します。喜んで彼らに報告したいのですが、彼らのメーリング リストはスパムに屈したようです。

于 2012-02-11T21:15:15.507 に答える