position ()! = last () не работает - PullRequest
0 голосов
/ 24 мая 2018

У меня есть XML как:

<ast>
    <group>
        <Set>
            <location line="1" column="22" offset="22"/>
            <group>
                <Id value="foo">
                    <location line="1" column="31" offset="31"/>
                </Id>
            </group>
            <group>
                <Function>
                    <location line="1" column="22" offset="22"/>
                    <end-location line="1" column="49" offset="49"/>
                    <group>
                        <Id value="a">
                            <location line="1" column="35" offset="35"/>
                        </Id>
                        <Id value="b">
                            <location line="1" column="37" offset="37"/>
                        </Id>
                    </group>
                    <group>
                        <Return>
                            <location line="1" column="40" offset="40"/>
                            <Number value="0">
                                <location line="1" column="47" offset="47"/>
                            </Number>
                        </Return>
                    </group>
                </Function>
            </group>
        </Set>
        ...
    </group>
</ast>

, который я обрабатываю с помощью этого шаблона:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="text()" /><!-- remove blanks -->

    <xsl:template match="Set[group[position()=1]/Id][group[position()=2]/Function]">
        <function-def>
            <xsl:attribute name="name">
                <xsl:value-of select="group[position()=1]/Id/@value" />
                <xsl:text>(</xsl:text>
                <xsl:apply-templates select="group[position()=2]/Function" />
                <xsl:text>)</xsl:text>
            </xsl:attribute>
            <xsl:copy-of select="group/Function/location" />
            <xsl:copy-of select="group/Function/end-location" />
        </function-def>
    </xsl:template>

    <xsl:template match="Function/group[position()=1]/Id">
        <xsl:value-of select="@value" />
        <xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
    </xsl:template>

</xsl:stylesheet>

, однако условие position() != last() в последнем шаблоне не работает.Почему?

Вывод отображается как:

<?xml version="1.0"?>
<function-def name="foo(a,b,)">...

, тогда как должно быть:

<?xml version="1.0"?>
<function-def name="foo(a,b)">...

1 Ответ

0 голосов
/ 24 мая 2018

Это работает, но не так, как вы думаете ....

В вашем первом шаблоне у вас есть это xsl:apply-templates

<xsl:apply-templates select="group[position()=2]/Function" />

Но у вас нет подходящего шаблонаFunction, и поэтому встроенный шаблон правил XSLT запускает, что это ...

<xsl:template match="*|/">
   <xsl:apply-templates/>
</xsl:template>

Это выберет элементы Group, для которых снова естьнет шаблона.Теперь, когда он делает <xsl:apply-templates/>, он выберет все дочерние узлы, включая пустые текстовые узлы, используемые для отступа в XML.

Проблема в том, что когда вы тестируете position() = last(), вы тестируете положениеэлемент в наборе всех выбранных дочерних узлов, который включает в себя текстовые узлы.После последнего id есть пустой текстовый узел, поэтому id может быть последним id элементом, но это не последний дочерний узел.

Одно из решений - сообщить XSLT обрезатьпустые текстовые узлы, так что id становится последним дочерним узлом

 <xsl:strip-space elements="*" />

В качестве альтернативы, вы можете добавить шаблон, соответствующий group, и явно выбрать только id узлов

<xsl:template match="Function/group[position()=1]">
    <xsl:apply-templates select="Id" />
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...