найти номер в строке xslt - PullRequest
2 голосов
/ 22 марта 2012

Мне нужно, чтобы я мог найти последнее вхождение числа в элементе.Например,

<DATA1>States45bx3.33</DATA1>
<DATA2>States45bx33</DATA2>

Из этой строки я хочу получить последнее значение числа в XSLT, т.е. 3.33 в 1-м случае и 33 во 2-м случае.Любая помощь будет оценена.

Ответы [ 2 ]

1 голос
/ 22 марта 2012

ОК, вот решение в XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <output>
            <xsl:for-each select="root/*">
                <xsl:element name="{name()}">
                    <xsl:call-template name="getEndNumber">
                        <xsl:with-param name="input" select="normalize-space(.)"/>
                        <xsl:with-param name="dotIncluded" select="true()"/>
                    </xsl:call-template>
                </xsl:element>
            </xsl:for-each>
        </output>
    </xsl:template>

    <xsl:template name="getEndNumber">
        <xsl:param name="input"/>
        <xsl:param name="dotIncluded"/>
        <xsl:variable name="len" select="string-length($input)"/>
        <xsl:choose>
            <xsl:when test="substring($input, $len, 1) &gt;= '0' and substring($input, $len, 1) &lt;= '9'">
                <xsl:call-template name="getEndNumber">
                    <xsl:with-param name="input" select="substring($input, 1, $len - 1)"/>
                    <xsl:with-param name="dotIncluded" select="$dotIncluded"/>
                </xsl:call-template>
                <xsl:value-of select="substring($input, $len, 1)"/>
            </xsl:when>
            <xsl:when test="substring($input, $len, 1) = '.' and $dotIncluded">
                <xsl:call-template name="getEndNumber">
                    <xsl:with-param name="input" select="substring($input, 1, $len - 1)"/>
                    <xsl:with-param name="dotIncluded" select="false()"/>
                </xsl:call-template>
                <xsl:value-of select="substring($input, $len, 1)"/>
            </xsl:when>
            <xsl:otherwise/>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

Применимо к

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <a>States45bx3.33</a>
    <b>States45bx33</b>
    <c>asdfs12310.13.0sads23.23</c>
    <d>asdfs12310.13.0sads23.23z</d>
    <e>asdfs12310.13.0sads23.23.34</e>
</root>

результат

<?xml version="1.0" encoding="UTF-8"?>
<output>
    <a>3.33</a>
    <b>33</b>
    <c>23.23</c>
    <d/>
    <e>23.34</e>
</output>
0 голосов
/ 22 марта 2012

Если вы можете применить XSLT 2.0, используйте следующее:

<xsl:value-of select="replace(., '.*[^.\d](\d*\.?\d+)$', '$1')"/>

Это вернет число в конце текущего узла, целое число или число с плавающей запятой.

Объяснение используемого регулярного выражения:
(1). * = Произвольное количество символов в начале строки
(2) [^. \ D] = один символ, который не является точкой и не цифрой
(3) (...) группировка, позволяющая отсылать назад по $ 1
(4) \ d *.? \ D + = необязательные цифры + необязательные точки + цифры
(5) $ = конец строки
(6) $ 1 возврат к группе 1

Поместить в xslt:

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

    <xsl:template match="/">
        <output>
            <xsl:for-each select="root/*">
                <num>
                    <xsl:value-of select="replace(., '.*[^.\d](\d*\.?\d+)$', '$1')"/>
                </num>
            </xsl:for-each>
        </output>
    </xsl:template>

</xsl:stylesheet>

Применяется для ввода

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <number>States45bx3.33</number>
    <number>States45bx33</number>
    <number>asdfs12310.13.0sads23.23</number>
</root>

Это приводит к

<?xml version="1.0" encoding="UTF-8"?>
<output>
    <num>3.33</num>
    <num>33</num>
    <num>23.23</num>
</output>

Вы можете поместить это в xsl: function (для этого также требуется XSLT 2.0), так что вы можете просто получить номер в конце, вызвав функцию, и сделать элементы, окружающие результат, выполненными вне функции:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:custom="http://customFunctions">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <output>
            <xsl:for-each select="root/*">
                <num>
                    <xsl:value-of select="custom:getNumberAtEnd(.)"/>
                </num>
            </xsl:for-each>
        </output>
    </xsl:template>

    <xsl:function name="custom:getNumberAtEnd">
        <xsl:param name="input"/>
        <xsl:value-of select="replace($input, '.*[^.\d](\d*.?\d+)$', '$1')"/>
    </xsl:function>

</xsl:stylesheet>

Примечание: если в конце строки нет числа, результатом вызова функции или более раннего оператора xsl: value-of будет вся входная строка. Если вы этого не хотите, вам сначала нужно проверить строку, или когда вы уверены, что конец строки всегда будет правильно сформированным числом, тогда вы можете заменить регулярное выражение на следующее, которое просто возвращает что-либо в конце после последней, не являющейся точкой, не цифры, которая может быть пустой строкой.

<xsl:value-of select="replace($input, '.*[^.\d](.*)$', '$1')"/>
...