2012-04-12 3 views
6

Ich habe eine Anwendung, die die SAXONHE 9.2.1.1 API-Dateien verwendet, um XML-Daten in reinen Text umzuwandeln. Meine Form hat Textfelder fürApp mit saxonHE (9.2.1.1) api zum Verarbeiten von XSLT (v2.0) gegen mehrere XML-Dateien

  1. XMLInput_FilePath
  2. XSLT_FilePath
  3. TextOutput_FilePath

Auf der okButton_Click() Ereignis meiner Form, ich habe folgendes:

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(); 
} 

Innerhalb der Kontext meiner XMLInput-Datei gibt es einen Verweis auf Daten in einer anderen XML-Datei - siehe unten:

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> 

Der Text Attribut ist, wo der externe XML-Dateipfad gespeichert ist, in dem obigen Beispiel der XML-Dateiname wäre "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> 

Ich verwende Microsoft Visual Studion 2008 Professional Edition meine Transformation zu testen und das obige Szenario funktioniert genau so, wie es sein sollte - das Dokument() referenzieren die externe Datei genauer. Wenn ich jedoch meine C# -Winform-App und die saxon-API-Aufrufe verwende, enthält meine Ausgabedatei leere Daten (Leerzeilen).

Nach ein paar Tests und Internetrecherchen bin ich zu dem Schluss gekommen, dass der relative Pfad [in meinem XSLT] nicht richtig angewendet wird. Es scheint, dass die saxon api Aufrufe die Datei document() aus dem Speicherort der Datei transform.exe und nicht die Eingabedatei verarbeiten (was ich bevorzuge).

Ich habe versucht, mehr Internet-Suchen zu diesem Thema zu tun, und ich bin verwirrt, ob das Problem in meiner XSLT-Datei oder in den saxon API-Aufrufen innerhalb der okButton_Click() -Ereignis ist. Außerdem war ich auf der saxon Website und documentation um Hilfe, aber ohne Erfolg.

Antwort

1

In Ihrem XSLT verwenden

<xsl:apply-templates select ="document($_intfFileName, /)/*[@Name=$_intfModelName]/*"> 

, wenn Sie die relative URL wollen Eingabedokument (und nicht die Sheet) aufgelöst relativ zu werden.

+0

ich die XSLT aktualisiert entsprechend Ihrer Antwort und ich bin immer noch der gleiche Ergebnis -. blank Daten – Lorentz

+0

ich einige andere Probleme mit Ihrer geschrieben Proben sehen, Sie haben ein 'Rows' Element mit einem' Path' Kind-Element mit einem 'Text' geschrieben Attribut noch Ihren Code ein nicht' for-each select = "//Rows "' und greift dann auf den '@ Text' dieser' Rows' Elemente zu, nicht auf das 'Path'-Kind. Also, basierend auf den geposteten Samples, könnte 'for-select =" // Rows/Path "' sein –

+0

Danke Martin - du hast Recht Aktualisierter Originalbeitrag – Lorentz

0

Nachdem ich meine Anfrage in der saxon help mailing-Liste gestellt hatte, half mir Michael Kay von Saxonica bei diesem Problem. Der Fehler war in meinen sächsischen API-Aufrufen (C# -Anwendung). Unten ist der aktualisierte Code:

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(); 
} 

„Das Problem ist, dass Sie Dokument() rufen eine relative URI dessen Basis-URI ist unbekannt zu lösen Da Sie die relative URI zu berechnen substring-before verwenden, die. Argument ist eine Zeichenkette, also wird der Basis-URI der des Stylesheets verwendet.Der Basis-URI des Stylesheets ist unbekannt, weil Sie das Stylesheet aus einem Stream erstellt haben; In dieser Situation gibt Saxon an das aktuelle Arbeitsverzeichnis aus. Sie können die Basis-URI mit der XsltCompiler.BaseUri Eigenschaft „ -. Micheal Kay

So, hier ist was ich getan habe

  • beide Filestream entfernt Variablen
  • ein XsltCompiler Objekt erstellt und festgelegt BaseUri in die Eingabedatei
  • ersetzt die FileStream-Signatur mit 'neue Uri (Dateiname)' Signatur
  • diese Zeile des Codes entfernt 'xsltTransformer.InputXmlResolver = null;'

Meine Ausgabe ist, wie es sein sollte Vielen Dank an Michael Kay von Saxonica für seine Hilfe bei der Lösung dieses -.. Lorentz

Verwandte Themen