Определить URL-адрес или адрес электронной почты в строке

Я пытаюсь обнаружить URL-адрес или адрес электронной почты в строковом элементе файла xml, к которому применяется этот xslt. Это часть кода, с которой я работаю:

<xsl:template match="/contacts/contact/other-contact">
    <xsl:value-of select="service"/>
    <xsl:choose>
            <xsl:when test="@type != ''">
                <xsl:text>(</xsl:text>
                <xsl:value-of select="@type"/>
                <xsl:text>)</xsl:text>
            </xsl:when>
        </xsl:choose>
    <xsl:text>: </xsl:text>
    <xsl:choose>
        <xsl:when test="matches(address,'(http(s?)://)?((www\.)?)(\w+\.)+.+')">
            <a href="{address}"><xsl:value-of select="address"/></a>
        </xsl:when>
        <xsl:when test="matches(address,'[^@]+@[^\.]+\.\w+')">
            <a href="mailto:{address}"><xsl:value-of select="address"/></a>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="address"/>
        </xsl:otherwise>
    </xsl:choose>
    <br/>
</xsl:template>

В соответствии с этот ответ matches(var,regex) должен просто работать, но это дает мне эту ошибку:

xmlXPathCompOpEval: function matches not found
XPath error : Unregistered function
xmlXPathCompiledEval: 2 objects left on the stack.

address является элементом /contacts/contact/other-contact


person Maroš Beťko    schedule 09.12.2017    source источник
comment
XPath существует в версиях 1, 2, 3 и 3.1, чтобы использовать функцию matches, вам нужно как минимум использовать XPath 2, как это делают процессоры XSLT 2. Сообщение об ошибке похоже на libxslt, который поддерживает только XSLT и XPath 1.0, и, в зависимости от конфигурации, EXSLT работает как xmlsoft.org/XSLT/EXSLT/html/libexslt-exslt.html.   -  person Martin Honnen    schedule 09.12.2017
comment
Я использую xsltproc для компиляции документа. Не уверен, какая у меня версия и как ее обновить. xsltproc -V дал мне этот вывод: Using libxml 20904, libxslt 10129 and libexslt 817 xsltproc was compiled against libxml 20904, libxslt 10129 and libexslt 817 libxslt 10129 was compiled against libxml 20904 libexslt 817 was compiled against libxml 20904   -  person Maroš Beťko    schedule 09.12.2017
comment
xsltproc и libxslt поддерживают только XSLT и XPath 1.0, поэтому вы не можете использовать их для XSLT и XPath 2 с matches. Saxon 9 поддерживает XSLT и XPath 2, а в версии 9.8 даже XSLT 3 и XPath 3.1, он доступен в версиях для Java, .NET и C.   -  person Martin Honnen    schedule 09.12.2017
comment
Класс, для которого я это делаю, использует xsltproc, поэтому я не уверен, смогу ли я использовать что-то еще. Есть ли другой способ проверить соответствие регулярного выражения тому, к чему у меня есть доступ?   -  person Maroš Beťko    schedule 09.12.2017


Ответы (1)


Функция fn:matches определяет, соответствует ли строка используемому синтаксису регулярного выражения, определенному схемой XML с некоторыми изменениями/дополнениями в XQueryXPath/XSLT 2.0.

Вероятно, вы используете XSLT 1.0, и безопасность будет заключаться в использовании функции contains с более четким объединением, как в примере ниже:

<xsl:template match="/contacts/contact/other-contact">  
    <!--check if type is not blank, otherwise it will pass blank-->    
    <xsl:variable name="var.type">            
        <xsl:if test="string-length(@type) &gt;0">                
            <xsl:value-of select="concat('(', @type, ')')"/>            
        </xsl:if>        
    </xsl:variable>
    <!--check address--> 
    <xsl:variable name="var.address">    
        <xsl:choose>        
            <xsl:when test="contains(address,'http') or contains(address,'www')">            
                <a href="{address}"><xsl:value-of select="address"/></a>  
            </xsl:when>        
            <xsl:when test="contains(address,'@')">            
                <a href="mailto:{address}"><xsl:value-of select="address"/></a>
            </xsl:when>        
            <xsl:otherwise>
              <xsl:value-of select="address"/>       
            </xsl:otherwise>   
        </xsl:choose>        
    </xsl:variable>      
    <!--safe concat all your result-->    
    <xsl:value-of select="concat(service, $var.type, ': ', $var.address)"/>

</xsl:template>
person Alex Fomin    schedule 10.12.2017
comment
Как я узнал, мы должны использовать XSLT 1.0, поэтому я думаю, что ваш ответ - лучший, который я могу получить без поддержки регулярных выражений. А также спасибо за подсказку, как собрать окончательный текст с помощью cocnat. - person Maroš Beťko; 10.12.2017