2017-02-22 85 views
0

我正在學習XSLT,並試圖過濾現有的XML文件,並且基本上只複製具有感興趣的選定節點的樹 - 如果它們匹配條件,比如說有子串「測試」。如何在XSL中篩選?

使用恆等變換模式,我有以下片段:

<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="(node() | @*)[contains(name(.), 'test')]" /> 

<!-- Bonus Q: What would be happening behind the scenes when I put this code inside the copy element? 
<xsl:value-of select="." /> --> 

    </xsl:copy> 
</xsl:template> 

現在,這個讓我下面的輸出,

<head> 
<testA> <testAChild /></testA> <!-- should be <testA> <testAChild> foo </testAChild></testA> --> 
<testB /> <!-- should be <testB> bar </testB> --> 
<Ctest /> <!-- should be <Ctest> foobar </Ctest> --> 
      <!-- should be <DontDeleteThis> <testD> 420 </testD></DontDeleteThis> --> 
</head> 

但是,它並沒有在結果中的值樹。此外,它不檢查每個情況,當前節點是錯誤的,但是兒童,孫輩或可能是盛大的孩子可以通過標準。

下面是輸入XML的例子:

<head> 
    <testA> 
     <testAChild> foo </testAChild> 
    </testA> 
    <testB> bar </testB> 
    <Ctest> foobar </Ctest> 
    <DeleteThis> DELETED </DeleteThis> 
    <DontDeleteThis> 
     <testD> 420 </testD> 
    </DontDeleteThis> 
</head> 
+0

請提供您的XML文件。 – AntonH

+0

@AntonH我編輯了這個問題,並用XML片段進行了更新。我正在尋找這種問題的通用解決方案,因此它應該足夠靈活以適應其他類型的XML結構。 – WCGPR0

回答

1

,後代元素名稱和後代處理指令名稱,你必須明確地這樣做。您的代碼僅檢查當前節點的名稱。如果要匹配屬性名稱,則需要確保屬性所附的元素不能被丟棄。例如:

<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0" xml:lang="en-latn"> 
    <output media-type="application/xml"/> 
    <template match="attribute::node() | child::node()"> 
     <copy> 
      <variable name="attributes" select="attribute::node()[contains(name(), 'test')]"/> 
      <variable name="elements" select="child::*[count((descendant-or-self::node() | attribute::node())[contains(name(), 'test')]) > 0]"/> 
      <variable name="comments" select="child::comment()[count(ancestor::node()[contains(name(), 'test')]) > 0]"/> 
      <variable name="PIs" select="child::processing-instruction()[count(ancestor-or-self::node()[contains(name(), 'test')]) > 0]"/> 
      <variable name="text" select="child::text()[count(ancestor::node()[contains(name(), 'test')]) > 0]"/> 
      <apply-templates select="$attributes | $elements | $comments | $PIs | $text"/> 
     </copy> 
    </template> 
</transform> 

另外值得一提的是,Rupesh的代碼將不匹配於處理指令(PI)節點名稱。 *node()之間存在細微的差異; *是元素節點的簡寫,除了attributenamespace軸之外,這意味着您必須使用node()來匹配PI節點。 (在XPath 2,有一個在element()/element(*)*相應的草書,我想知道,使這一概念少一點混亂。)

至於你的獎金問題,value-of元素運行選擇的節點上string XPath函數。因此,對於所有匹配的元素,元素的字符串值(即所有文本節點連接起來)將輸出到元素的位置。對於匹配的屬性,註釋,處理指令和文本節點,由於copy元素忽略了其節點類型的內容,因此不會輸出其他文本。

1

使用本

<xsl:template match="node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()[descendant-or-self::*[contains(name(.), 'test')]]" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="node()[contains(name(.), 'test')]"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

如果你想匹配的祖先元素的名稱,它會給你的願望輸出