我一直在寻找一种方法来检查Web应用程序部署描述符(web.xml)中是否存在特定的“servlet-mapping”,如果在使用XSLT 1.0维护Schema有效性时未找到则添加它,但是,我会睁大眼睛试图解决这个问题并继续进行,并且可能会让它变得更加困难。
根据Java Servlet规范,“servlet-mapping”元素必须遵循“servlet”(如果存在),如果已定义,则必须遵循“listener”元素等等。
那么,只有在“servlet-mapping”尚未出现的情况下,如何在所有其他“servlet”元素之后添加“servlet-mapping”元素。
这是一个配对的web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.5"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>/jsp/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
</web-app>
这是我的XSLT,遗憾的是,如果不存在,则将“servlet-mapping”元素放在web.xml的开头:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:param name="version.jsp.servlet.name" select="'jsp'"/>
<xsl:param name="version.jsp.url.pattern" select="'/jsp/*'"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="jee:web-app">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:if test="not(jee:servlet-mapping[jee:servlet-name=$version.jsp.servlet.name and jee:url-pattern=$version.jsp.url.pattern])">
<xsl:message>Adding jsp servlet-mapping</xsl:message>
<xsl:element name="servlet-mapping">
<xsl:element name="servlet-name">
<xsl:value-of select="$version.jsp.servlet.name"/>
</xsl:element>
<xsl:element name="url-pattern">
<xsl:value-of select="$version.jsp.url.pattern"/>
</xsl:element>
</xsl:element>
</xsl:if>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我尝试在XPath表达式中使用“follow-sibling”无效,如下所示:
not(jee:servlet[position()=last()]/following-sibling::jee:servlet-mapping[jee:servlet-name=$version.jsp.servlet.name and jee:url-pattern=$version.jsp.url.pattern])
我还需要在XML中添加一个“filter”元素后跟一个“filter-mapping”元素,但是,在这种情况下,我显然需要在所有“icon”,“display-name”之后添加它们,“描述“,”distributable“和”context-param“元素,如果它们存在的话。
如果它们一直存在,我将如何构造一个XPath表达式来解释前面所需的元素?
答案 0 :(得分:0)
如果你把xsl:if放在你的apply-templates之后,它应该可以工作。
但也许添加这样的模板也可以帮到你:
<!-- It's the last servlet of the input -->
<xsl:template match="jee:servlet[not(following-sibling::jee:servlet)]">
<!-- First do as usual and copy the servlet -->
<xsl:next-match/>
<!-- Then test if you need to output some specific mapping -->
<xsl:if test="not(jee:servlet-mapping[jee:servlet-name=$version.jsp.servlet.name and jee:url-pattern=$version.jsp.url.pattern])">
...
</xsl:if>
</xsl:template>
但是在你的问题中使用position()不能像你想的那样工作,因为你需要“上下文中的最后一个servlet”,而不是“只有当它是上下文中的最后一个元素时才是一个servlet”。 我想通过模板示例,您将能够解决“过滤器案例”。
如果您遇到XSLT 1.0,xsl:next-match将无效。只需为您的通用模板命名(匹配+名称属性)并显式调用它而不是xsl:next-match。
答案 1 :(得分:0)
我建议使用它:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee"
exclude-result-prefixes="jee">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:param name="version.jsp.servlet.name" select="'jsp'"/>
<xsl:param name="version.jsp.url.pattern" select="'/jsp/*'"/>
<xsl:template match="@*|node()" name="Copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="jee:servlet[last()]">
<xsl:call-template name="Copy" />
<xsl:if test="not(../jee:servlet-mapping
[jee:servlet-name = $version.jsp.servlet.name and
jee:url-pattern = $version.jsp.url.pattern])">
<xsl:call-template name="ServletMapping" />
</xsl:if>
</xsl:template>
<xsl:template name="ServletMapping">
<servlet-mapping>
<servlet-name>
<xsl:value-of select="$version.jsp.servlet.name"/>
</servlet-name>
<url-pattern>
<xsl:value-of select="$version.jsp.url.pattern"/>
</url-pattern>
</servlet-mapping>
</xsl:template>
</xsl:stylesheet>