2012-06-15 96 views
2

我有一個外部設置文件,其中有一些節點holid屬性值的主要xml文檔。如果屬性值在設置文件中存在,我需要從mian xml文件中刪除certian節點。基於外部文件刪除元素

我的設置文件看起來是這樣的:

Setting.xml的

<xml> 
    <removenode titlename="abc" subtitlename="xyz"></removenode> 
    <removenode titlename="dvd" subtitlename="dvd"></removenode> 

</xml> 

main.xml中

<xml> 
    <title titlename="abc"> 
     <subtitle subtitlename="xyz"></subtitle> 
     </title> 
     <title titlename="book"> 
      <subtitle subtitlename="book sub title"></subtitle> 
     </title> 
</xml> 

需要一個腳本,尋找Setting.xml的文件,並刪除標題元素如果在main.xml中找到titlename和subtitlename。輸出應該

的Output.xml

<xml> 
     <title titlename="book"> 
      <subtitle subtitlename="book sub title"></subtitle> 
     </title> 
</xml> 

我嘗試使用文檔閱讀Setting.xml的文件,但無法找到如何做的main.xml文件比賽

<xsl:variable name="SuppressionSettings" select="document('Setting.xml')" /> 
    <xsl:variable name="SuppressSetting" select="$SuppressionSettings/xml/removenode" /> 

任何提示如何實現它?

+0

會發生什麼事,當你試圖用'文件代碼( )'? –

+0

我從外部文件獲取值,但不知道如何爲main.xml編寫匹配模板,即 atif

+0

Your * Main.xml *和* output.xml *格式不正確。請更正此問題,以便將來的讀者可以將問題與答案(即將發佈的內容)一起重現。 –

回答

2

關鍵是使用身份/複製模式,並且在每次輸出之前,檢查當前(上下文)節點是否被抑制規則節點集禁止。

<!-- get suppression settings --> 
    <xsl:variable name='suppression_settings' select="document('http://www.mitya.co.uk/xmlp/settings.xml')/xml/removenode" /> 


    <!-- begin identity/copy --> 

    <xsl:template match="node()|@*"> 
     <xsl:if test='not($suppression_settings[@titlename = current()/@titlename and @subtitlename = current()/subtitle/@subtitlename])'> 
      <xsl:copy> 
       <xsl:apply-templates select='node()|@*' /> 
      </xsl:copy> 
     </xsl:if> 
    </xsl:template> 

你可以在這裏運行(見輸出源 - 省略了 'ABC' 稱號節點):

http://www.xmlplayground.com/9oCYKp

+0

您的邏輯完全錯過了subtilename ... – atif

+0

已編輯。你是,呃,歡迎。 – Utkanos

+0

謝謝Marzipan,如果我在設置文件中交換字幕名稱值,它仍然會壓縮標題,因爲它應該不會,除非標題名稱和字幕名稱在同一節點內匹配。上述代碼的問題在於它會查找任何具有titlename和subtitlename的獨立removeode值。因爲它應該查找來自同一節點的兩個值。 – atif

0

這XSLT下述適用於給定的文件。

請注意,我將Setting.xml的內容存儲在一個變量中,但是,我會直接在我的查詢中使用該變量。

這裏的一個重要問題是在templatematch元素中,不能使用變量。因此,我的模板與任何<title>元素相匹配,然後在<xsl:choose>元素中確定屬性是否與設置文件中給出的任何值相匹配 - 如果是,則輸出中將省略<title>元素。

至於爲什麼在<xsl:when>test屬性的解釋做什麼應該,想象someAttribute = someOtherAttribute比較沒有這種限制屬性someAttribute必須具有相同的值屬性someOtherAttribute,而是作爲條件那必須有任何兩個屬性someAttributesomeOtherAttribute具有相同的值

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:variable name="SuppressionSettings" select="document('Setting.xml')" /> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="//title"> 
     <xsl:choose> 
      <xsl:when test="(@titlename = $SuppressionSettings/xml/removenode/@titlename) and (subtitle/@subtitlename = $SuppressionSettings/xml/removenode/@subtitlename)"/> 
      <xsl:otherwise> 
       <xsl:copy> 
        <xsl:apply-templates select="node()|@*"/> 
       </xsl:copy> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 
+0

問題在於,如果設置文件具有低於其值的值,那麼它也會抑制標題。在下面設置文件的情況下,它不應該被壓制。 atif

+0

所以我只是在設置文件中交換字幕名稱的值,它仍然禁止標題,因爲它不應該除非titlename和subtitlename在同一節點內匹配。 – atif

+0

@atif:哦,對,它不會在同一設置節點中查找屬性值。抱歉。由於另一個答案已經顯示了正確的版本,我現在要離開它。 –

0

這裏有一個更通用的答案在屬性的名稱不硬編碼到XSLT。像O.R.Mapper指出的那樣,在XSLT 1.0中,你不能在match中使用變量引用,所以我把document()直接放在謂詞中。這可能不如使用變量然後測試變量那樣有效。

XSLT 1.0

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

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*[@* = document('setting.xml')/*/removenode/@*]"/> 

</xsl:stylesheet> 

XML輸出(使用2個XML文件與main.xml中作爲輸入)

<xml> 
    <title titlename="book"> 
     <subtitle subtitlename="book sub title"/> 
    </title> 
</xml> 
+0

它沒有尋找字幕名稱。所以不是我所期待的。 – atif