XSLT插入正确的位置

时间:2017-11-01 20:50:41

标签: xslt xslt-1.0 xslt-2.0 xslt-grouping

我的输入XML如下。基本上,XML有各种<servlet-name>标签。我的要求是应用一个XSLT转换,它浏览<B>标签并查看是否存在具有指定名称的特定servlet。如果它存在,那么我需要看到具有<param-name>的特定servlet下的标记<param-name>不存在。如果搜索下的特定<B>NEW</B>标记不存在,那么我会添加标记<B>以及该特定servlet的其他<web-app metadata-complete="true"> <servlet> <servlet-name>AAA</servlet-name> <servlet-class>com.AAA</servlet-class> <B> <param-name>port</param-name> <param-value>8802</param-value> </B> <B> <param-name>connectors-xml</param-name> <param-value/> </B> <B> <param-name>webservices-xml</param-name> <param-value/> </B> <B> <param-name>exposure-server</param-name> <param-value/> </B> <some-tag>1</some-tag> </servlet> <servlet> <servlet-name>BBB</servlet-name> <servlet-class>com.BBB</servlet-class> <B> <param-name>port</param-name> <param-value>8802</param-value> </B> <B> <param-name>connectors-xml</param-name> <param-value/> </B> <B> <param-name>webservices-xml</param-name> <param-value/> </B> <B> <param-name>exposure-server</param-name> <param-value/> </B> <some-tag>2</some-tag> </servlet> <C> <D> </D </C> <junk-tag> <tag1>BASIC</tag1> <tag2>BASIC</tag2> </junk-tag> </web-app> 标记,否则我不会执行任何操作。< / p>

INPUT XML

<B>

例如。假设我在下面搜索Servlet名称为“BBB”的Servlet。如果找到,那么我检查其<param-name>标签<servlet-name>值XXX不存在,然后我添加它,以便o / p如下所示。如果“BBB”<B>的{​​{1}}标记<param-name>已经存在XXX,那么我什么都不做。

的Output.xml

<web-app metadata-complete="true">
<servlet>
    <servlet-name>AAA</servlet-name>
    <servlet-class>com.AAA</servlet-class>

    <B>
        <param-name>port</param-name>
        <param-value>8802</param-value>
    </B>
    <B>
        <param-name>connectors-xml</param-name>
        <param-value/>
    </B>
    <B>
        <param-name>webservices-xml</param-name>
        <param-value/>
    </B>
    <B>
        <param-name>exposure-server</param-name>
        <param-value/>
    </B>
    <some-tag>1</some-tag>
</servlet>

<servlet>
    <servlet-name>BBB</servlet-name>
    <servlet-class>com.BBB</servlet-class>

    <B>
        <param-name>port</param-name>
        <param-value>8802</param-value>
    </B>
    <B>
        <param-name>connectors-xml</param-name>
        <param-value/>
    </B>
    <B>
        <param-name>webservices-xml</param-name>
        <param-value/>
    </B>
    <B>
        <param-name>exposure-server</param-name>
        <param-value/>
    </B>

    <B>NEW</B>

    <some-tag>2</some-tag>
</servlet>

<C>
    <D>   
     </D
</C>

<junk-tag>
    <tag1>BASIC</tag1>
     <tag2>BASIC</tag2>
</junk-tag>
</web-app>

我曾尝试编写XSLT,但不知何故遇到了BUGS和语法问题

    <xsl:template match="web-app/servlet[servlet-name='BBB/B']">
   <xsl:copy-of select="."/>
    <xsl:choose>
        <xsl:when test="not(/web-app/servlet[servlet-name='BBB']/B[param-name='XXX'])">
            <B>NEW</B>
        </xsl:when>
    </xsl:choose>
</xsl:template>

任何指导?我对XSLT很有兴趣,并尝试使用谷歌搜索。

1 个答案:

答案 0 :(得分:1)

您想要的表达式仅为not(B[param-name='XXX']),因为您已经定位在该点的相关servlet上,因此该表达式将与此相关。此外,您当前的代码将复制现有的servlet并在其后添加<B>NEW</B>,而实际上您希望将其作为孩子。

所以你可以这样做....

<xsl:template match="web-app/servlet[servlet-name='BBB']">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <xsl:if test="not(B[param-name='XXX'])">
            <B>NEW</B>
        </xsl:if>
    </xsl:copy>
</xsl:template>

或者更好的是,将支票放入模板匹配本身

<xsl:template match="web-app/servlet[servlet-name='BBB'][not(B[param-name='XXX'])]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <B>NEW</B>
    </xsl:copy>
</xsl:template>

(这两个假设您也使用identity template

但是,这会在<some-tag>2</some-tag>之后添加您的新标记,这可能不是您想要的。

如果要将其放在最后一个B元素之后,则应更改模板以匹配最后一个B元素。

<xsl:template match="web-app/servlet[servlet-name='BBB'][not(B[param-name='XXX'])]/B[last()]">
    <xsl:copy-of select="." />
    <B>NEW</B>
</xsl:template>

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="web-app/servlet[servlet-name='BBB'][not(B[param-name='XXX'])]/B[last()]">
        <xsl:copy-of select="." />
        <B>NEW</B>
    </xsl:template>

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