2017-02-11 76 views
0

我斯威夫特應用程序產生一個XMLDocument,它然後變換使用XSLT:如何在Swift中使用EXSLT或XSL 2處理XMLDocument?

xmlDocument.object(byApplyingXSLTString: xsltString, arguments: nil) 

在我的XSLT樣式表(xsltString),我想訪問使用XPath結果樹片段。這在XSLT 1.0中不受支持;我嘗試過使用XSLT 2.0,但似乎沒有得到Swift的支持;在xsl:stylesheet元素指定version="2.0"產生這個錯誤:

xsl:version: only 1.0 features are supported 


我想我可以用node-set從EXSLT。我對此並不熟悉,但我試圖將關於EXSLT的信息添加到xsl:stylesheet元素中。這似乎沒有任何效果:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common" 
    extension-element-prefixes="exsl" 
    version="1.0"> 

我收到以下錯誤:

xmlXPathCompOpEval: function node-set not found 
XPath error : Unregistered function 


是否有可能在我的情況下使用XSL 2.0或EXSLT,怎麼樣?

+0

考慮向我們展示你已經嘗試了最小但完整的示例。 XSLT 1.0處理器在專有名稱空間中不支持「exsl:node-set」或類似函數是很常見的。因此,找出Swift使用哪個XSLT處理器,並希望能夠將結果樹片段轉換爲節點集。 –

+1

嘗試運行一個簡單的測試用例,如http://xsltransform.net/3NSSEvF中的樣式表到您的處理器。 –

+0

謝謝。使用你鏈接到的樣式表,我看到Swift使用libxslt。但是,我一直無法走得更遠:我試着用'libxslt:','xt:'和'saxon:'作爲前綴'node-set',如文檔[here](http://xmlsoft.org/XSLT /html/libxslt-extra.html#xsltFunctionNodeSet),但總會得到相同的錯誤:'xmlXPathCompOpEval:function node-set not found'。 –

回答

0

Martin Honnen的建議讓我考慮使用xsltproc而不是使用Swift的object(byApplyingXSLTString:arguments:)方法。

下面是結果的樣子。

斯威夫特代碼

// Write XML to temporary file 
xmlDocument.xmlString.write(to: temporaryXMLFileURL, atomically: false, encoding: String.Encoding.utf8) 

// Use xsltproc to apply the XSLT transformation 
let task = Process() 
task.launchPath = "/usr/bin/xsltproc" 
task.arguments = try [xsltFileURL.absoluteString, temporaryXMLFileURL.absoluteString] 
let pipe = Pipe() 
task.standardOutput = pipe 
task.launch() 
let data = pipe.fileHandleForReading.readDataToEndOfFile() 
let xsltResult = String(data: data, encoding: .utf8)! 

XSLT代碼

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exslt="http://exslt.org/common" 
    extension-element-prefixes="exslt" 
    version="1.0"> 

    <xsl:variable name="stuff"> 
     ... 
    </xsl:variable> 

    <xsl:for-each select="exslt:node-set($stuff)/stuff"> 
     ... 
    </xsl:for-each> 

</xsl:stylesheet>