使用XSLT过滤基于另一个xml的XML 1

问题描述:

如何根据另一个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

这是必要的改造:

 
<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. 将模板应用于元素子元素时,会找到其相应节点并将其作为预期参数传递。

请尽情享受!

嗯,你有点谈论合并(假设你的过滤器的文档是可变的)。有几种可能性会随着您所实施的语言的不同而有所不同。您能否提供有关该应用程序的更多信息?

否则,我建议快速谷歌“xslt +合并”,看看是否有一些结果抓住你。

基于什么我已经在过去,当类似的问题面对我建议做:

  • 写XSLT转换,其消耗的“过滤器XML”而产生的变换(也XSLT)。
  • 在输入上运行生成的XSLT。

它听起来(而且)是丑陋的,但我发现这比在转换输入时试图解释动态过滤器描述更容易。