6

SAXONHE 9.2.1.1 API ファイルを使用して XML データをプレーン テキストに変換するアプリケーションがあります。私のフォームにはテキストボックスがあります

  1. XMLInput_FilePath
  2. XSLT_FilePath
  3. TextOutput_FilePath

私のフォームのokButton_Click()イベントには、次のものがあります。

private void okButton_Click(object sender, EventArgs e) {
    FileStream xsltTransform_FileStream = File.Open(xsltTransform_FilePath.Text, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    FileStream xmlInput_FileStream = File.Open(xmlInput_FilePath.Text, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

    XmlTextReader modelFileXML = new XmlTextReader(xmlInput_FileStream);
    modelFileXML.XmlResolver = null;

    Processor processor = new Processor();

    XdmNode input = processor.NewDocumentBuilder().Build(modelFileXML);

    XsltTransformer xsltTransformer = processor.NewXsltCompiler().Compile(xsltTransform_FileStream).Load();
    xsltTransformer.InputXmlResolver = null;
    xsltTransformer.InitialContextNode = input;

    Serializer serializer = new Serializer();
    serializer.SetOutputFile(writeFile);

    xsltTransformer.Run(serializer);

    xsltTransform_FileStream.Close();
    modelFileStream.Close();
}

XMLInput ファイルのコンテキスト内に、別の XML ファイル内のデータへの参照があります。以下を参照してください。

XML:

<XMLInput_File
  Name="XMLInput_File">
  <Subsystem Name="Subsystem">
    <Requirements Name="Requirement_1">
      <Rows>
        <Path Text="XMLInput2_File:/XMLInput2_File/Subsystem_1/Field_1" />
      </Rows>
      <Rows>
        <Path Text="XMLInput2_File:/XMLInput2_File/Subsystem_1/Field_2" />
      </Rows>
    </Requirements>
    <Requirements Name="Requirement_2">
      <Rows>
        <Path Text="XMLInput2_File:/XMLInput2_File/Subsystem_1/Field_3" />
      </Rows>
      <Rows>
        <Path Text="XMLInput2_File:/XMLInput2_File/Subsystem_2/Field_1" />
      </Rows>
    </Requirements>
  </Subsystem>
</XMLInput_File>

Text 属性は、外部 XML ファイル パスが格納される場所です。上記の例では、XML ファイル名は「XMLInput2_File.xml」になります。

XML2:

<XMLInput2_File Name="XMLInput2_File">
  <Subsystem Name="Subsystem_1">
    <Fields Name="Field_1">
      S1_Field_One
    </Fields>
    <Fields Name="Field_2">
      S1_Field_Two
    </Fields>
     <Fields Name="Field_3">
      S1_Field_Three
    </Fields>
 </Subsystem>
  <Subsystem Name="Subsystem_2">
    <Fields Name="Field_1">
      S2_Field_One
    </Fields>
    <Fields Name="Field_2">
      S2_Field_Two
    </Fields>
     <Fields Name="Field_3">
      S2_Field_Three
    </Fields>
 </Subsystem>
</XMLInput2_File>

XSLT:

  <xsl:template match="/">
    <xsl:for-each select ="//Rows/Path">
      <xsl:variable name ="interfaceData" select ="@Text"/>
      <xsl:variable name ="_intfModelName" select ="substring-before(@Text,':/')"/>
      <xsl:variable name ="_intfFileName" select ="concat('../../OtherXMLFiles/',$_intfModelName,'.xml')"/>
      <xsl:apply-templates select ="document($_intfFileName)/*[@Name=$_intfModelName]/*">
      </xsl:apply-templates>
     </xsl:for-each>
  </xsl:template>

私は Microsoft Visual Studion 2008 Professional Edition を使用して変換をテストしていますが、上記のシナリオは、外部ファイルをより具体的に参照する document() が正確に機能します。ただし、C# Winform アプリと saxon API 呼び出しを使用すると、出力ファイルに空白のデータ (空白行) が含まれます。

いくつかのテストとインターネット検索の後、[XSLT 内の] 相対パスが適切に適用されていないという結論に達しました。saxon api 呼び出しは、入力ファイルではなく、transform.exe ファイルの場所から document() 関数を処理しているようです (これは私が好むものです)。

この問題についてさらにインターネット検索を試みましたが、問題が XSLT ファイルにあるのか、okButton_Click() イベント内の saxon API 呼び出しにあるのか混乱しています。さらに、私は saxon の Web サイトとドキュメントに助けを求めましたが、役に立ちませんでした。

4

2 に答える 2

0

私の質問をsaxonhelp-mailing-listに投稿した後、SaxonicaのMichaelKayがこの問題について私を助けてくれました。エラーは私のsaxonapi呼び出し(C#アプリケーション)にありました。更新されたコードは次のとおりです。

private void okButton_Click(object sender, EventArgs e) {
    Processor processor = new Processor();
    XdmNode input = processor.NewDocumentBuilder().Build(new Uri(inputFile));
    XsltCompiler compiler = processor.NewXsltCompiler();
    compiler.BaseUri = new Uri(inputFile);
    XsltTransformer xsltTransformer = compiler.Compile(new Uri(transformFileTextBox.Text)).Load();
    xsltTransformer.InitialContextNode = input;
    Serializer serializer = new Serializer();
    serializer.SetOutputFile(writeFile);
    xsltTransformer.Run(serializer);
    xsltTransform_FileStream.Close();
    modelFileStream.Close();
} 

「問題は、ベースURIが不明な相対URIを解決するためにdocument()を呼び出していることです。substring-beforeを使用して相対URIを計算するため、引数は文字列であるため、使用するベースURIは次のようになります。スタイルシート。ストリームからスタイルシートを作成したため、スタイルシートのベースURIは不明です。この状況では、Saxonはデフォルトで現在の作業ディレクトリになります。XsltCompiler.BaseUriプロパティを使用してベースURIを設定できます。」-ミシェルケイ

だから、これが私がしたことです

  • 両方のFileStream変数を削除しました
  • XsltCompilerオブジェクトを作成し、BaseUriを入力ファイルに設定しました
  • FileStream署名を'newUri(filename)'署名に置き換えました
  • このコード行を削除しました'xsltTransformer.InputXmlResolver= null;'

私の出力はあるべき姿です。これを解決するのを手伝ってくれたSaxonicaのMichaelKayに感謝します。-ローレンツ

于 2012-04-13T21:08:12.163 に答える