2012-04-12 21 views
6

Tôi có một ứng dụng sử dụng các tệp api SAXONHE 9.2.1.1 để chuyển đổi dữ liệu XML thành văn bản thuần túy. hình thức của tôi có textbox choỨng dụng sử dụng saxonHE (9.2.1.1) api để xử lý XSLT (v2.0) đối với nhiều tệp XML

  1. XMLInput_FilePath
  2. XSLT_FilePath
  3. TextOutput_FilePath

Trên okButton_Click() sự kiện về hình thức của tôi, tôi đã điều sau đây:

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

Trong ngữ cảnh của tệp XMLInput của tôi có tham chiếu đến dữ liệu trong một tệp XML khác - xem bên dưới:

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> 

Thuộc tính Text là nơi con đường XML file bên ngoài được lưu trữ, trong ví dụ trên, tên tập tin XML sẽ là "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> 

Tôi đang sử dụng Microsoft Visual Studion 2008 Professional Edition để thử nghiệm chuyển đổi của tôi và kịch bản trên hoạt động chính xác như mong muốn - tài liệu() tham chiếu tệp bên ngoài cụ thể hơn. Tuy nhiên, khi tôi sử dụng ứng dụng C# Winform và các cuộc gọi saxon api, tệp đầu ra của tôi chứa dữ liệu trống (các dòng trống).

Sau một vài thử nghiệm và tìm kiếm trên Internet, tôi đã đi đến kết luận rằng đường dẫn tương đối [trong XSLT] của tôi không được áp dụng như mong muốn. Có vẻ như saxon api gọi quá trình hàm document() từ vị trí của tệp transform.exe và không phải là tệp đầu vào (đó là những gì tôi muốn).

Tôi đã cố gắng thực hiện nhiều tìm kiếm trên Internet hơn về vấn đề này và tôi nhầm lẫn về vấn đề nằm trong tệp XSLT của tôi hay trong cuộc gọi saxon api trong sự kiện okButton_Click(). Hơn nữa, tôi đã đến trang web của saxon và documentation để được trợ giúp, nhưng vô ích.

Trả lời

1

Trong XSLT của bạn, sử dụng

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

nếu bạn muốn URL có liên quan để được giải quyết liên quan đến các tài liệu đầu vào (và không phải là stylesheet).

+0

tôi cập nhật XSLT theo trả lời của bạn và tôi vẫn nhận được cùng Kết quả - dữ liệu trống – Lorentz

+0

Tôi thấy một số vấn đề khác với mẫu đã đăng của bạn, bạn đã đăng phần tử 'Rows' với phần tử con' Đường dẫn' có thuộc tính 'Văn bản' nhưng mã của bạn thực hiện' for-each select = "//Rows "' và sau đó truy cập vào '@ Text' của những phần tử' Rows', không phải của con 'Path'. Vì vậy, dựa trên các mẫu đã đăng bạn có thể muốn' for-each select = "// Rows/Path" ' –

+0

Xin cảm ơn Martin - chính xác là bạn đã cập nhật bài viết gốc – Lorentz

0

Sau khi đăng câu hỏi của tôi về danh sách gửi thư giúp đỡ saxon, Michael Kay của Saxonica đã giúp tôi giải quyết vấn đề này. Lỗi trong các cuộc gọi saxon api của tôi (C# applicaiton). Dưới đây là mã Cập nhật:

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

"Vấn đề là bạn đang gọi tài liệu() để giải quyết một URI tương đối có cơ sở URI không rõ Bởi vì bạn sử dụng chuỗi-trước để tính URI tương đối, các. đối số là một chuỗi, do đó, URI cơ sở nó sẽ sử dụng là của biểu định kiểu.URI cơ bản của biểu định kiểu không xác định vì bạn đã tạo biểu định kiểu từ luồng; trong tình huống này, Saxon mặc định vào thư mục làm việc hiện tại. Bạn có thể thiết lập các cơ sở URI sử dụng tài sản XsltCompiler.BaseUri " -. Micheal Kay

Vì vậy, đây là những gì tôi đã làm

  • loại bỏ cả hai biến FileStream
  • tạo một đối tượng XsltCompiler và thiết lập BaseUri vào tệp đầu vào
  • thay thế chữ ký FileStream bằng chữ ký 'new Uri (filename)' chữ ký
  • đã xóa dòng mã này 'xsltTransformer.InputXmlResolver = null;'

đầu ra của tôi là như nó phải được Rất cám ơn Michael Kay của Saxonica sự giúp đỡ của ông trong việc giải quyết này -.. Lorentz

Các vấn đề liên quan