2013-05-08 4 views
1

Я пытаюсь использовать функцию, чтобы найти все числа из элемента или строки. Количество номеров и их статистика не должны иметь значения. Ранее я написал следующие функции:Как найти все числа в строке

<xsl:function name="itp:find_num"> 
<xsl:param name="tmp"/> 
<xsl:if test="matches($tmp,'\d+')"> 
    <xsl:analyze-string select="$tmp" regex="{'\d+'}"> 
     <xsl:matching-substring> 
      <xsl:sequence select="."/> 
     </xsl:matching-substring> 
     <xsl:non-matching-substring> 
      <xsl:value-of select="''"/> 
     </xsl:non-matching-substring> 
    </xsl:analyze-string> 
</xsl:if> 
</xsl:function> 

пример XML:

<address>street 12, 12345 town<address> 

В вызове функции должно быть соответствующее число может быть выбрано:

...select="itp:find_num(address)[2]"/> 

К примеру, 2 для Почтовый индекс. Проблема в том, что в последовательности также есть пустые значения, так что на практике я достигаю почтовый индекс только с помощью [4].

Есть ли более элегантный способ решить мою проблему? И если нет, как удалить пустые элементы из последовательности?

Сейчас на английском языке :-)

Я пытаюсь найти все числа в строке или элемента. Не имеет значения, сколько номеров доступны или в каком положении они находятся в строке.

Вот моя функция:

<xsl:function name="itp:find_num"> 
<xsl:param name="tmp"/> 
<xsl:if test="matches($tmp,'\d+')"> 
    <xsl:analyze-string select="$tmp" regex="{'\d+'}"> 
     <xsl:matching-substring> 
     <xsl:if test=". != ''"> 
      <xsl:sequence select="."/> 
     </xsl:if> 
     </xsl:matching-substring> 
     <xsl:non-matching-substring> 
      <xsl:value-of select="''"/> 
     </xsl:non-matching-substring> 
    </xsl:analyze-string> 
</xsl:if> 
</xsl:function> 

Пример XML

<address>street 12, 12345 town<address> 

Когда я вызываю функцию, я хочу, чтобы выбрать, какой номер я хочу, чтобы выбрать:

...select="itp:find_num(address)[2]"/> 

Par пример [2] для почтового кода. Проблема У меня есть, что в последовательности есть пустые элементы, поэтому я должен выбрать [4], чтобы получить почтовый код.

Есть ли способ решить мою проблему? Или есть способ удалить все пустые элементы в этой последовательности?

Спасибо :-)

+0

Christian Manthey, Вас может заинтересовать более простое, более короткое, чистое решение XPath. –

ответ

1

я бы написать функцию, как

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:mf="http://example.org/mf" 
    exclude-result-prefixes="xs mf"> 

<xsl:function name="mf:find_num" as="xs:integer*"> 
    <xsl:param name="input" as="xs:string"/> 
    <xsl:analyze-string select="$input" regex="[0-9]+"> 
    <xsl:matching-substring> 
     <xsl:sequence select="xs:integer(.)"/> 
    </xsl:matching-substring> 
    </xsl:analyze-string> 
</xsl:function> 

<xsl:template match="address"> 
    <xsl:value-of select="mf:find_num(.)" separator=", "/> 
</xsl:template> 

</xsl:stylesheet> 

Конечно преобразования в xs:integer не является обязательным, если вы хотите, чтобы функция возвращает последовательность строк, содержащих цифры вы бы просто изменить это сделать

<xsl:function name="mf:find_num" as="xs:string*"> 
    <xsl:param name="input" as="xs:string"/> 
    <xsl:analyze-string select="$input" regex="[0-9]+"> 
    <xsl:matching-substring> 
     <xsl:sequence select="."/> 
    </xsl:matching-substring> 
    </xsl:analyze-string> 
</xsl:function> 
+0

Ну, это было очень легко. Не знал, что несовпадающая подстрока не нужна. Возможно, я неправильно понял функцию «строка-анализ». Большое спасибо, это именно то, что я искал :-) –

+0

Это, безусловно, можно сделать проще. –

2

Там нет необходимости в сложной xsl:analyze-string обработки на всех.

Это XPath один вкладыш:

for $i in tokenize($pStr, '[^0-9]+')[.] 
    return xs:integer($i) 

производит разыскиваемого последовательность целых чисел в строке:

12 12345 

Вот полное преобразование:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my"> 
<xsl:output method="text"/> 

<xsl:template match="/*"> 
    <xsl:sequence select="my:nums(.)"/> 
</xsl:template> 

<xsl:function name="my:nums" as="xs:integer*"> 
    <xsl:param name="pStr" as="xs:string"/> 

    <xsl:sequence select= 
    "for $i in tokenize($pStr, '[^0-9]+')[.] 
    return xs:integer($i)"/> 
</xsl:function> 
</xsl:stylesheet> 

Когда это преобразование применяются на предоставленном документе XML:

<address>street 12, 12345 town</address> 

производится разыскиваемый, правильный результат:

12 12345 

Даже проще, XPath 3.0 один -liner:

tokenize($pStr, '[^0-9]+')[.] ! xs:integer(.) 
+0

Спасибо за ответ, но я получаю эту ошибку: Последовательность нескольких элементов не допускается в результате функции itp: find_num() –

+0

@ChristianManthey, Вероятно, у вас есть ошибка копирования/вставки. Пожалуйста, обратите внимание на то, как функция определена в ответе: 'as =" xs: integer * "'. Я предполагаю, что вы опустили атрибут 'as' или неправильно его переписали. –

+0

Вот и все. Я забыл *. Отличное решение! Спасибо! –

Смежные вопросы