2008-12-03 95 views
2

如何根據另一個xml文檔過濾xml文檔。我必須刪除查找xml中不存在的所有元素。輸入xml和查找xml都具有相同的根元素,我們使用的是XSLT 1.0。使用XSLT過濾基於另一個xml的XML 1

例輸入

<Root> 
    <E1 a="1">V1</E1> 
    <E2>V2</E2> 
    <E3>V3</E3> 
    <E5> 
     <SE51>SEV1</SE51>  
     <SE52>SEV2</SE52>  
    </E5> 
    <E6> 
     <SE61>SEV3</SE61>  
     <SE62>SEV4</SE62>  
    </E6> 
</Root> 

過濾器的Xml

<Root> 
    <E1 a="1"></E1> 
    <E2></E2> 
    <E5> 
     <SE51></SE51>  
     <SE52></SE52>  
    </E5> 
</Root> 

期望輸出

<Root> 
    <E1 a="1">V1</E1> 
    <E2>V2</E2> 
    <E5> 
     <SE51>SEv1</SE51>  
     <SE52>SEV2</SE52>  
    </E5> 
</Root> 
+0

您的XML已損壞:需要引用屬性值。 也不匹配。 – bendin 2008-12-03 09:38:51

+0

謝謝,更新了xml – 2008-12-03 09:43:55

回答

3

這是必要的改造:

 
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:z="inline:text.xml" 
exclude-result-prefixes="z" 
> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <z:filter> 
     <Root> 
      <E1 a="1"></E1> 
      <E2></E2> 
      <E5> 
       <SE51></SE51> 
       <SE52></SE52> 
      </E5> 
     </Root> 
    </z:filter> 

    <xsl:variable name="vFilter" select= 
    "document('')/*/z:filter"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="*[name()=name($vFilter/*)]"> 
     <xsl:with-param name="pFiltNode" select="$vFilter/*"/> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:param name="pFiltNode"/> 

     <xsl:copy> 
     <xsl:copy-of select="@*"/> 

     <xsl:for-each select="text() | *"> 
     <xsl:choose> 
      <xsl:when test="self::text()"> 
      <xsl:copy-of select="."/> 
      </xsl:when> 
      <xsl:otherwise> 
      <xsl:variable name="vFiltNode" 
       select="$pFiltNode/*[name()=name(current())]"/> 

      <xsl:apply-templates select="self::node()[$vFiltNode]"> 
       <xsl:with-param name="pFiltNode" select="$vFiltNode"/> 
      </xsl:apply-templates> 
      </xsl:otherwise> 
     </xsl:choose> 
     </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

當下面的XML文檔(原一加加入<SE511>SEV11</SE511>應用這種轉變表明,篩選適用於任何級別

 
<Root> 
    <E1 a="1">V1</E1> 
    <E2>V2</E2> 
    <E3>V3</E3> 
    <E5> 
     <SE51>SEV1</SE51> 
     <SE511>SEV11</SE511> 
     <SE52>SEV2</SE52> 
    </E5> 
    <E6> 
     <SE61>SEV3</SE61> 
     <SE62>SEV4</SE62> 
    </E6> 
</Root> 

想要的結果產生

 
<Root> 
    <E1 a="1">V1</E1> 
    <E2>V2</E2> 
    <E3>V3</E3> 
    <E5> 
     <SE51>SEV1</SE51> 
     <SE511>SEV11</SE511> 
     <SE52>SEV2</SE52> 
    </E5> 
    <E6> 
     <SE61>SEV3</SE61> 
     <SE62>SEV4</SE62> 
    </E6> 
</Root> 

請注意到以下細節的該溶液

  1. 模板僅應用於具有所述過濾器的文檔中的匹配節點並且還這樣的元件的所有文本節點的元素。
  2. 匹配元素的模板作爲參數傳遞給filter-document中的相應節點。
  3. 將模板應用於元素子元素時,會找到其相應節點並將其作爲預期參數傳遞。

請盡情享受!

0

嗯,你有點談論合併(假設你的過濾器的文檔是可變的)。有幾種可能性會隨着您所實施的語言的不同而有所不同。您能否提供有關該應用程序的更多信息?

否則,我建議快速谷歌「xslt +合併」,看看是否有一些結果抓住你。

0

基於什麼我已經在過去,當類似的問題面對我建議做:

  • 寫XSLT轉換,其消耗的「過濾器XML」而產生的變換(也XSLT)。
  • 在輸入上運行生成的XSLT。

它聽起來(而且)是醜陋的,但我發現這比在轉換輸入時試圖解釋動態過濾器描述更容易。