Вставка XSLT в правильном месте

Мой входной XML выглядит следующим образом. В основном XML имеет различные теги <servlet>. Мое требование состоит в том, чтобы применить преобразование XSLT, которое просматривает теги <servlet-name> и проверяет, существует ли конкретный сервлет с указанным именем. Если он существует, мне нужно увидеть, что тег <B> под этим конкретным сервлетом с <param-name> не СУЩЕСТВУЕТ. Если тег с определенным <param-name> в искомом не существует, я добавляю тег <B>NEW</B> вместе с другими тегами <B> этого конкретного сервлета, иначе я не выполняю никаких действий.

ВВОД 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>
    <some-tag>2</some-tag>
</servlet>

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

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

например. Допустим, я ищу сервлет с именем сервлета как «BBB» ниже. Если он найден, то я проверяю, что его тег <B> со значением <param-name> XXX не существует, а затем добавляю его, чтобы o/p выглядел, как показано ниже. Если "BBB" <servlet-name> уже имеет тег <B> со значением <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, но каким-то образом столкнулся с ОШИБКАМИ и проблемами синтаксиса.

    <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 и пытаюсь сам погуглить.


person TestUser    schedule 01.11.2017    source источник


Ответы (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>

(В обоих случаях предполагается, что вы также используете шаблон удостоверения)

Однако это добавит ваш новый тег после <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>
person Tim C    schedule 01.11.2017
comment
Большое тебе спасибо. Ваше решение расширяет мои знания для решения подобных проблем в будущем. - person TestUser; 02.11.2017