2012-04-12 14 views
6

Ho un'applicazione che utilizza i file API di SAXONHE 9.2.1.1 per trasformare i dati XML in testo normale. La mia forma ha le caselle di testo perApp che utilizza saxonHE (9.2.1.1) api per elaborare XSLT (v2.0) su più file XML

  1. XMLInput_FilePath
  2. XSLT_FilePath
  3. TextOutput_FilePath

Sul caso okButton_Click() della mia forma, ho il seguente:

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

All'interno del contesto del mio file XMLInput c'è un riferimento ai dati in un altro file XML - vedi sotto:

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> 

L'attributo testo è dove è memorizzato il percorso del file XML esterno, nell'esempio di cui sopra, il nome del file XML sarebbe "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> 

sto utilizzando Microsoft Visual Studion 2008 Professional Edition per testare la mia trasformare e lo scenario di cui sopra funziona esattamente come dovrebbe - il documento() facendo riferimento al file esterno in modo più specifico. Tuttavia, quando uso la mia app C# Winform e le chiamate ax saxon, il mio file di output contiene dati vuoti (righe vuote).

Dopo alcuni test e ricerche su Internet, sono giunto alla conclusione che il percorso relativo [nel mio XSLT] non viene applicato come dovrebbe. Sembra che le chiamate a saxon api elaborino la funzione document() dalla posizione del file transform.exe e non il file di input (che è quello che preferirei).

Ho cercato di fare più ricerche su Internet su questo problema e sono confuso dal fatto che il problema sia nel mio file XSLT o nelle chiamate a saxon all'interno dell'evento okButton_Click(). Inoltre, sono stato a visitare il sito Web di saxon e documentation per aiuto, ma senza alcun risultato.

risposta

1

Nel vostro XSLT, utilizzare

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

se si desidera che l'URL relativo da risolvere rispetto al documento di input (e non il foglio di stile).

+0

ho aggiornato il XSLT secondo la vostra risposta e sto ancora ricevendo lo stesso risultato - dati vuoti – Lorentz

+0

Vedo altri problemi con i tuoi campioni pubblicati, hai pubblicato un elemento 'Rows' con un elemento figlio' Path' con un attributo 'Text' ma il tuo codice esegue un' for-each select = "//Righe "' e quindi accede a '@ Text' di quegli elementi' Rows', non del figlio 'Path'. Quindi, in base agli esempi pubblicati, si potrebbe desiderare' for-each select = "// Rows/Path" ' –

+0

Grazie Martin - hai ragione, ha aggiornato il post originale – Lorentz

0

Dopo aver inviato la mia richiesta sulla mailing-list di saxon, Michael Kay di Saxonica mi ha aiutato con questo problema. L'errore era nelle mie chiamate a saxon api (C# applicationiton). Di seguito è riportato il codice aggiornato:

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

"Il problema è che si sta chiamando documento() per risolvere un URI relativo cui base URI è sconosciuto poiché si utilizza sottostringa-prima per calcolare l'URI relativo, il. argomento è una stringa, quindi l'URI di base che userà è quello del foglio di stile.L'URI di base del foglio di stile è sconosciuto perché hai creato il foglio di stile da uno stream; in questa situazione, le impostazioni predefinite di Saxon vengono visualizzate nella directory di lavoro corrente. È possibile impostare l'URI di base utilizzando la proprietà XsltCompiler.BaseUri " -. Micheal Kay

Così, ecco quello che ho fatto

  • rimosse entrambe le variabili FileStream
  • creato un oggetto XsltCompiler e impostare BaseUri al file di input
  • sostituito la firma FileStream con 'new Uri (nome)' firma
  • rimosso questa riga di codice 'xsltTransformer.InputXmlResolver = null;'

La mia uscita è come dovrebbe essere Molte grazie a Michael Kay di Saxonica per il suo aiuto nella risoluzione di questo -.. Lorentz

Problemi correlati