2

我们如何根据另一个 xml 文档过滤一个 xml 文档。我必须删除查找 xml 中不存在的所有元素。输入 xml 和查找 xml 都具有相同的根元素,我们使用的是 XSLT 1.0。

防爆输入

<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>
4

3 回答 3

3

这是所需的转换:

<xsl:stylesheet 版本="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:z="内联:text.xml"
 排除结果前缀=“z”
 >
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <z:过滤器>
        <根>
            <E1 a="1"></E1>
            <E2></E2>
            <E5>
                <SE51></SE51>
                <SE52></SE52>
            </E5>
        </根>
    </z:过滤器>

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

    <xsl:模板匹配="/">
      <xsl:apply-templates select="*[name()=name($vFilter/*)]">
        <xsl:with-param name="pFiltNode" select="$vFilter/*"/>
      </xsl:apply-templates>
    </xsl:模板>

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

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

       <xsl:for-each select="text() | *">
         <xsl:选择>
           <xsl:when test="self::text()">
             <xsl:copy-of select="."/>
           </xsl:when>
           <xsl:否则>
            <xsl:变量名="vFiltNode"
                 select="$pFiltNode/*[name()=name(current())]"/>

            <xsl:apply-templates select="self::node()[$vFiltNode]">
              <xsl:with-param name="pFiltNode" select="$vFiltNode"/>
            </xsl:apply-templates>
           </xsl:否则>
         </xsl:选择>
       </xsl:for-each>
      </xsl:copy>
    </xsl:模板>
</xsl:样式表>

当此转换应用于以下 XML 文档时(原始文件加上 <SE511>SEV11</SE511>证明过滤适用于任何级别

<根>
    <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>
</根>

产生了想要的结果

<根>
    <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>
</根>

请注意此解决方案的以下详细信息

  1. 模板仅适用于过滤文档中具有匹配节点的元素,也适用于此类元素的所有文本节点。
  2. 匹配元素的模板作为参数传递给过滤器文档中的相应节点。
  3. 将模板应用于元素子时,会找到其对应的节点并将其作为预期参数传递。

尽情享受吧!

于 2008-12-04T04:40:59.453 回答
0

嗯,您是在谈论合并(假设您的过滤器文档是可变的)。有几种可能性会因您实现所有这些的语言而异。您能否提供有关该应用程序的更多信息?

否则,我建议在“xslt +merge”上快速搜索一下,看看那里是否有一些结果抓住了你。

于 2008-12-03T09:26:03.437 回答
0

根据我过去遇到类似问题时所做的事情,我建议:

  • 在 XSLT 中编写一个转换,向其消耗“过滤 XML”并生成一个转换(也在 XSLT 中)。
  • 在您的输入上运行生成的 XSLT。

这听起来(并且是)丑陋,但我发现这比在转换输入时尝试即时解释过滤器描述更容易。

于 2008-12-03T09:35:04.230 回答