2016-01-20 69 views
0

我有一個XML文件,需要使用XSLT 2.0基於映射文件進行轉換。我正在使用Saxon HE處理器。XSLT 2.0動態XPATH表達式

我的映射文件:

<element root="TEST"> 
    <childName condition="/TEST/MyElement/CHILD[text()='B']>/TEST/MyElement/CHILD</childName> 
    <childBez condition="/TEST/MyElement/CHILD[text()='B']>/TEST/MyElement/CHILDBEZ</childBez> 
</element> 

我當孩子的文本等於B. 複製元素的子和CHILDBEZ加上家長和根元素,因此與此輸入:

<?xml version="1.0" encoding="UTF-8"?> 
<TEST> 
    <MyElement> 
     <CHILD>A</CHILD> 
     <CHILDBEZ>ABEZ</CHILDBEZ> 
     <NotInteresting></NotInteresting> 
    </MyElement> 
    <MyElement> 
     <CHILD>B</CHILD> 
     <CHILDBEZ>BBEZ</CHILDBEZ> 
     <NotInteresting2></NotInteresting2> 
    </MyElement> 
</TEST> 

<TEST> 
    <MyElement> 
     <childName>B</childName> 
     <childBez>BBEZ</childBez> 
    </MyElement> 
</TEST> 

是我迄今(基於這樣的:

所需的輸出解決方案XSLT 2.0 XPATH expression with variable):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
<xsl:strip-space elements="*"/> 

<xsl:param name="mapping" select="document('mapping.xml')"/> 

<xsl:key name="map" match="*" use="."/> 

<xsl:template match="/"> 
    <xsl:variable name="first-pass"> 
     <xsl:apply-templates mode="first-pass"/> 
    </xsl:variable> 
    <xsl:apply-templates select="$first-pass/*"/> 
</xsl:template> 

<xsl:template match="*" mode="first-pass"> 
    <xsl:param name="parent-path" tunnel="yes"/> 
    <xsl:variable name="path" select="concat($parent-path, '/', name())"/> 
    <xsl:variable name="replacement" select="key('map', $path, $mapping)"/> 
    <xsl:variable name="condition" select="key('map', $path, $mapping)/@condition"/>   
    <xsl:choose> 
     <xsl:when test="$condition!= ''"> 
      <!-- if there is a condition defined in the mapping file, check for it --> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:element name="{if ($replacement) then name($replacement) else name()}"> 
       <xsl:attribute name="original" select="not($replacement)"/> 
       <xsl:apply-templates mode="first-pass"> 
        <xsl:with-param name="parent-path" select="$path" tunnel="yes"/> 
       </xsl:apply-templates> 
      </xsl:element> 
     </xsl:otherwise> 
    </xsl:choose> 

</xsl:template> 

<xsl:template match="*"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*[@original='true' and not(descendant::*/@original='false')]"/>  
</xsl:stylesheet> 

但問題是,這是不可能的XSLT 2.0評估動態XPath表達式。有沒有人知道這個解決方法?另外我有一個映射文件的問題。當它只有一個元素時,它根本不工作。

+0

爲什麼你需要那個映射文件?難道你不能只寫一個帶有模板和適當匹配模式的樣式表嗎?通過使用該映射格式並希望使用動態XPath評估您會獲得什麼?您是否考慮過使用一個XSLT從您的映射生成另一個XSLT來完成這項工作? –

+0

我需要一個映射文件,因爲我有來自不同提供者的不同輸入XML文件,並且我認爲只需爲所有輸入文件創建一個映射文件就是一個不錯的可讀解決方案。但我也必須考慮其他解決方案。使用XSLT生成另一個XSLT聽起來不錯,我會試試這個。非常感謝你。 –

回答

1

如果動態XPath評估不是您選擇的處理器中的選項,那麼生成XSLT樣式表通常是一個不錯的選擇。事實上,無論如何,這通常是一個很好的選擇。

思考此問題的一種方式是您的映射文件實際上是一種用非常簡單的轉換語言編寫的程序。有兩種執行此程序的方法:可以編寫解釋器(動態XPath評估),也可以編寫編譯器(XSLT樣式表生成)。兩者都很好。