使用 XSLT 1 根据另一个 xml 过滤 XML [英] Filter XML based on another xml using XSLT 1

查看:24
本文介绍了使用 XSLT 1 根据另一个 xml 过滤 XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

防爆输入

<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

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

预期输出

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

解决方案

这是所需的转换:

<前><xsl:stylesheet version="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="*"/><根><E1 a="1"></E1></z:过滤器><xsl:variable name="vFilter" select="文档('')/*/z:filter"/><xsl:template match="/"><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:copy-of select="@*"/><xsl:for-each select="text() | *"><xsl:when test="self::text()"><xsl:copy-of select="."/></xsl:when><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>证明过滤适用于任何级别:

<前><根>V1V2V3SEV1SEV11SEV2SEV3<SE62>SEV4</SE62>

产生想要的结果:

<前><根>V1V2V3SEV1SEV11SEV2SEV3<SE62>SEV4</SE62>

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

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

尽情享受吧!

How do we filter an xml document based on another xml document. I have to remove all the elements which are not there in the lookup xml. Both the input xml and lookup xml has the same root elements, we are using XSLT 1.0.

Ex Input

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

Filter Xml

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

Expected Output

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

解决方案

Here is the required transformation:

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

When this transformation is applied on the following XML document (the original one plus the addition of <SE511>SEV11</SE511> to demonstrate that the filtering works on any level:

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

the wanted result is produced:

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

Do notice the following details of this solution:

  1. Templates are applied only to elements that have a matching node in the filter-document and also to all text nodes of such elements.
  2. The template that matches an element is passed as parameter the corresponding node in the filter-document.
  3. When applying templates to an element-child, its corresponding node is found and passed as the expected parameter.

Do enjoy!

这篇关于使用 XSLT 1 根据另一个 xml 过滤 XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆