2012-06-20 1 views
6

Я экспериментирую с проблемой с оператором < по строкам в Xpath 1.0.Как сравнить строки с Xpath 1.0?

Это простое выражение Xpath

'A' < 'B' (or the equivalent 'A' &lt; 'B') 

не вычисляться правда в моем XSLT работать в LibXSLT (который является XSLT 1.0 двигатель).

Я проверил в XML Spy, который позволяет тестировать выражения Xpath как в 1.0, так и 2.0, и, конечно же, в Xpath 2.0 он оценивается как true, но в Xpath 1.0 он оценивается как false!

Это ошибка в Xpath 1.0?

Какое другое выражение следует использовать для сравнения двух строк/символов для их алфавитного порядка? Обратите внимание, что функция compare() не будет работать, так как это функция XSLT 2.0.

ответ

4

Да, это ограничение XPath 1.0. (Я не думаю, что разумно ссылаться на ограничение, которое вам не нравится, как на «ошибку», хотя разработчики XPath 2.0 согласились с вами, что это нежелательное ограничение).

Вы помечены свой вопрос «XSLT», так что вы можете быть в состоянии обойти эту проблему на уровне XSLT, по крайней мере, если ваш процессор имеет множество узлов расширения на:

<xsl:variable name="nodes"> 
    <node><xsl:value-of select="$A"/></node> 
    <node><xsl:value-of select="$B"/></node> 
</xsl:variable> 

<xsl:for-each select="exslt:node-set($nodes)/*"> 
    <xsl:sort select="."/> 
    <xsl:if test="position()=1 and .=$A">A comes first!</xsl:if> 
</xsl:for-each> 

Но, возможно, пришло время перейти на 2.0. Что вас удерживает?

+0

Спасибо Michael - приятное компактное решение. Что касается XSLT 2.0, то что меня удерживает - 'libxslt' is - это движок, используемый' php 5', и я не могу его изменить. Возможно, в будущем мой хостинг-провайдер будет использовать версию php, которая использует движок XSLT 2.0 - когда он есть. Я действительно хотел бы сделать все это в XSLT 2.0, конечно, на самом деле я сделал для развития, а затем пришлось переписать все. Я предполагаю, что одна и та же причина не для перехода на XSLT 2.0 для большого числа разработчиков XSLT. – Maestro13

+0

@ Maestro13: Zobra поддерживает XPath 2.0 и доступен как расширение PHP, см. Http://www.ibm.com/developerworks/xml/library/x-zorba/index.html. Что касается PHP, вы можете также [зарегистрировать функции PHP] (http://php.net/manual/en/domxpath.registerphpfunctions.php), как 'strcmp', который будет использоваться с вашим xpath. – hakre

+0

@hakre спасибо за информацию - я поеду с моим провайдером хостинга, смогут ли они активировать Zobra. И да, альтернативой было бы зарегистрировать пользовательскую функцию php и использовать ее в xslt - в разгар битвы XSLT я полностью забыл об этом. – Maestro13

1

Это может быть уродливое решение и нецелесообразно во многих ситуациях, но для простого сравнения в алфавитном порядке вы можете использовать translate. Следующий фрагмент является лишь примером, который может быть продлен furtherly:

translate('A','ABCD','1234') &lt; translate('B','ABCD','1234'); 

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

+0

так это ошибка, и это обход? тьфу! – Maestro13

+0

Просто предел. Посмотрите на http://www.xsltfunctions.com/xsl/c0008.html#c0017 –

+0

Я думаю, что этот подход ставит «D» перед «AA» (4 <11) –

7

В XPath 1.0 сравнение строк определяется только для = и !=, а сравнения сравнения недоступны. Спецификация говорит

Когда ни сравниваемых объектов является набор узлов, а оператор < =, <,> = или>, то объекты сравниваются путем преобразования обоих объектов к числам и сравнивая номера в соответствии с IEEE 754.

Таким образом, оба операнда преобразуются в поплавок, что делает их и NaN.

Я верю, что XML Microsoft добавляет функции расширения, чтобы справиться с этим, но, конечно, это помогает, только если вы используете MSXML.

2

В надежде, что это окажется полезным и для других, ниже приведен код, который я написал после предложения Майкла Кей. Я написал пользовательскую функцию compare, которая дает те же результаты, что и Xpath 2.0. Я также добавил тег php к вопросу, чтобы его можно было найти чаще.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:func="http://exslt.org/functions" 
    xmlns:common="http://exslt.org/common" 
    xmlns:custom="urn:myCustomFunctions" 
    exclude-result-prefixes="func common custom" 
    extension-element-prefixes="func custom"> 

    <xsl:output method="xml"/> 

    <func:function name="custom:compare"> 
     <xsl:param name="string1"/> 
     <xsl:param name="string2"/> 

     <func:result> 
      <xsl:choose> 
       <xsl:when test="$string1 = $string2">0</xsl:when> 
       <xsl:otherwise> 
        <xsl:variable name="nodes"> 
         <node><xsl:value-of select="$string1"/></node> 
         <node><xsl:value-of select="$string2"/></node> 
        </xsl:variable> 
        <xsl:for-each select="common:node-set($nodes)/*"> 
         <xsl:sort select="."/> 
         <xsl:choose> 
          <xsl:when test="position()=1 and .=$string1">-1</xsl:when> 
          <xsl:when test="position()=1 and .=$string2">1</xsl:when> 
         </xsl:choose> 
        </xsl:for-each> 
       </xsl:otherwise> 
      </xsl:choose> 
     </func:result> 
    </func:function> 

    <xsl:template match="/"> 
     <out> 
      <test1><xsl:value-of select="custom:compare('A', 'B')"/></test1> 
      <test2><xsl:value-of select="custom:compare('A', 'A')"/></test2> 
      <test3><xsl:value-of select="custom:compare('C', 'B')"/></test3> 
      <test4><xsl:value-of select="custom:compare('DD', 'A')"/></test4> 
     </out> 
    </xsl:template> 

</xsl:stylesheet> 

Результат выполнения этого (с фиктивным входом) является

<?xml version="1.0"?> 
<out> 
    <test1>-1</test1> 
    <test2>0</test2> 
    <test3>1</test3> 
    <test4>1</test4> 
</out> 

Для тех, кто хочет проверить это в PHP для себя, вот код, который я использовал:

<?php 
$xslt = new XSLTProcessor(); 
$xslt->importStylesheet(DOMDocument::load('testCompare.xslt')); 
$xslt -> registerPHPFunctions(); 
$xml = new SimpleXMLElement('<test/>'); 
print $xslt->transformToXML($xml); 
?> 

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

  • Нет связанных вопросов^_^