0

XSLT 1.0でスキーマの有効性を維持しながら、Webアプリケーションデプロイメント記述子(web.xml)に特定の「servlet-mapping」が存在するかどうかを確認し、見つからない場合は追加する方法を探していましたが、 m目を細めて、それを理解し、円を描き続けようとしますが、おそらくそれを実際よりも難しくしています。

Javaサーブレット仕様によれば、「servlet-mapping」要素は「servlet」が存在する場合はそれに続く必要があり、「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式で「following-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])

また、「filter」要素の後に「filter-mapping」要素をXMLに追加する必要がありますが、この場合は、明らかに「icon」、「display-name」、「description」、 「distributable」要素と「context-param」要素が存在する場合。

上記の必須要素が存在する場合、それらを考慮してXPath式を作成するにはどうすればよいですか?

4

2 に答える 2

0

apply-templates の後に xsl:if を配置すると、動作するはずです。

しかし、このようなテンプレートを追加すると、あなたにも役立つかもしれません:

<!-- 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() の使用は、「コンテキスト内の最後の要素である場合のみのサーブレット」ではなく、「コンテキスト内の最後のサーブレット」が必要なため、希望どおりに機能しません。テンプレートの例で、「フィルター ケース」を解決できると思います。

また、XSLT 1.0 に固執している場合、xsl:next-match は機能しません。ジェネリック テンプレートに名前を付けて (match + name 属性)、xsl:next-match の代わりに明示的に呼び出すだけです。

于 2013-03-14T18:01:19.810 に答える
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>
于 2013-03-14T18:57:07.017 に答える