dyn: define() не оценивает правильно?

По какой-то причине мой запрос XPath не работает, когда выполняется внутри XSLT через dyn:valu (). Я использую PHP и hasEXSLTSupport() оценивает true

Вот мой сырой XML-документ:

<getListValues>
    <node>
        <Assignee>Assignee Value</Assignee>
        <Summary>Summary Value</Summary>
        <Incident_Number>Incident_Number Value</Incident_Number>
    </node>
</getListValues>

Я использую это заявление XPath:

//node[Assignee!=""]/*[name()="Summary" or name()="Incident_Number" or  name()="Assignee"]

И в моем XSLT я использую этот раздел, чтобы проверить, работает ли он:

<xsl:variable name="elementValue" select="dyn:evaluate($query)" />
<xsl:value-of select="$elementValue" />

куда $query оценивает строку с выражением XPath (я знаю, потому что я проверил с xsl:value-of также).

Я не получаю никаких ошибок. На самом деле, делая <xsl:value-of select="boolean($elementValue)" /> оценивает false! Это означает, что ничего не возвращается.

Мои заголовки таблицы стилей:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dyn="http://exslt.org/dynamic" xmlns:php="http://php.net/xsl" extension-element-prefixes="dyn">

Кажется, что XPath просто не оценивается, даже если он совершенно корректен (я проверял PHP и Notepad++ с расширением XPatherizerNPP). Что мне не хватает?

РЕДАКТИРОВАТЬ

Мои настоящие сценарии находятся внутри нескольких классов и папок, поэтому я публикую более простую версию того, что я запускаю. Это эквивалентно тому, что dyn: valu () по-прежнему не работает, хотя Notepad++ говорит мне, что должен, и что я просто скопировал и вставил функции в другие классы в один для удобства.

Мой mock.xml - это скрипт, который я анализирую

<getListValues>
<node>
    <Assignee>Assginee Value</Assignee>
    <Summary>Summary Value</Summary>
    <Incident_Number>Incident_Number Value</Incident_Number>
</node>

мой countFieldValues.xml Таблица стилей вызывает PHP для одновременного анализа отдельных поддеревьев в вызове функции readSubtree php.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dyn="http://exslt.org/dynamic" xmlns:php="http://php.net/xsl" extension-element-prefixes="dyn">

    <xsl:output method="html" omit-xml-declaration="yes" />

    <xsl:template match="/">
        <xsl:call-template name="nodeIterate" />
    </xsl:template>

    <xsl:template name="nodeIterate">
        <xsl:variable name="subtree" select="php:functionString('xsltMaster::readSubtree', $dataset)" />
        <xsl:if test="boolean($subtree)">
            <xsl:apply-templates select="$subtree"/>
            <xsl:call-template name="nodeIterate" />
        </xsl:if>
    </xsl:template>

    <xsl:template match="node">
        <br/>The current node: <xsl:value-of select="." /><br/>
        <br/>The query: <xsl:value-of select="$query" /><br/>
        <xsl:variable name="elementValue" select="dyn:evaluate($query)" />
        <br/>What dyn:evaluate() evaluates to: <xsl:value-of select="boolean($elementValue)" /><br/>
        <xsl:if test="boolean($elementValue)">
            <xsl:for-each select="$elementValue">
                <br/>What dyn:evaluate() evaluates to specifically: <xsl:value-of select="$elementValue" /><br/><br/>
            </xsl:for-each>
            <!--<xsl:variable name="archivist" select="php:functionString('xsltMaster::storeCount', $element, $elementValue)" />-->
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

мой testscript.php вызывает класс и выполняет все

<?php

require_once "class.php";
$source = "countFieldValues.xml";

$query = '//node[Assignee!=""]/*[name()="Summary" or name()="Incident_Number" or  name()="Assignee"]';
$test4 = new xsltMaster;
$test4->createXSLT($source);

$test4->processDataSet($query, "mock.xml", "processedMock.json");

Мой class.php - процессор. Он использует классы XMLReader и XSLTProcessor в PHP.

<?php
class xsltMaster{

    protected static $_read;
    private $_xslt;
    protected $_dom;

    public function __construct(){
        // load DOM XML
        $this->_dom = new DOMDocument();
        $this->_dom->loadXML('<root />');
    }

    /*
        Creates the XSLT object on the currently loaded DOM document
        If the XSLT is already loaded, it will delete it
        It will then load the stylesheet
    */
    public function createXSLT($xsl){
        if(!empty($this->getXSLT())){
            $this->deleteXSLT();
        }
        $xsldoc = new DOMDocument();
        if(!$xsldoc->load($xsl)){
            throw new PDOException('Failed to open XML stylesheet!');
        }
        $this->getXSLT(new XSLTProcessor())->importStyleSheet($xsldoc);
        unset($xsldoc);

        return true;
    }

    /*
        Getters/setters for the XSLT processor
    */
    protected function getXSLT($xslt=false){
        if(!empty($xslt)){
            $this->_xslt = $xslt;
        }
        return $this->_xslt;
    }


    // this will register PHP functions and run PHP XMLReader inside XSLT
    public function processDataSet($query, $source, $destination){
        // set-up
        $this->getXSLT()->registerPHPFunctions();
        $this->getXSLT()->setParameter('', 'query', $query);
        $this->getXSLT()->setParameter('', 'dataset', $source);
        $this->getXSLT()->setProfiling('profile9.txt');
        echo "has EXSLT support? ", var_dump($this->getXSLT()->hasEXSLTSupport()), "<br/>";

        // execute
        print $this->getXSLT()->transformToXML($this->_dom);
        #file_put_contents($destination, json_encode(self::$_countList));

        // clean up
        $this->getXSLT()->removeParameter('', 'dataset');
        $this->getXSLT()->removeParameter('', 'query');
    }

    public static function readSubtree($url=false){
        // check if reader has already been initialized
        if(empty(self::$_read)){
            // if reader has not been initialized, check if a url is supplied
            if(empty($url)) throw new PDOException("There is no file defined for transformation!");
            // create the reader
            self::$_read = new XMLReader;
            self::$_read->open($url);
            // loop until you reach the first node
            while (self::$_read->name !== 'node'){
                self::$_read->read();
            }
        } else {
            // if the logic gets here, the reader has already initialized
            // just move to the next node
            self::$_read->next();
        }
        // once you find the first subtree, return it
        // as long as we're still landing on a node element, return that expanded subtree
        if(self::$_read->name === 'node'){
            #echo "<pre>",var_dump(self::$_read->getReader()->expand()),"</pre>";
            return self::$_read->expand();
        }
        // if it gets here, then we're at the bottom of the file
        return null;
    }

}

ОБНОВИТЬ:

Я нашел несколько выражений, для которых dyn:evaluate() возвращает наборы узлов. Но они немного странные.

Вот когда они оценивают как истинное:

Assignee
Summary
Incident Number
*[name()="Assignee"]
*[name()="Assignee" and text()="Assignee Value"]

Но они оценивают как ложные:

*[Assignee="Assignee Value"]
//Assignee

В чем дело...?

ОБНОВИТЬ:

По предложению Майкла я провел его тест и получил такой результат:

<?xml version="1.0" encoding="UTF-8"?>
<results>
  <processor>libxslt</processor>
  <support>true</processor>
  <path>/root/bravo</path>
  <target/>
</results>

Часть отказа - цель, является пустым элементом.

1 ответ

Я бы посоветовал вам попробовать гораздо более простой тест и сообщить о результатах:

XML

<root>
    <alpha/>
    <bravo/>
    <charlie/>
</root>

XSLT

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

<xsl:param name="path" select="'/root/charlie'"/>

<xsl:template match="/">
    <results>
        <processor>
            <xsl:value-of select="system-property('xsl:vendor')"/> 
        </processor>
        <support>
            <xsl:value-of select="function-available('dyn:evaluate')"/>
        </support>
        <path>
            <xsl:value-of select="$path"/>
        </path> 
        <target>
            <xsl:copy-of select="dyn:evaluate($path)"/>
        </target>   
    </results>
</xsl:template>

</xsl:stylesheet>

параметр

path = "/root/bravo"

Ожидаемый результат

<?xml version="1.0" encoding="UTF-8"?>
<results>
  <processor>libxslt</processor>
  <support>true</support>
  <path>/root/bravo</path>
  <target>
    <bravo/>
  </target>
</results>

2.

В ответ на ваши результаты:

Либо dyn:valu () не работает, несмотря на указания, либо что-то не так с тем, как вы передаете параметр. Это можно определить, добавив еще один элемент в тесты:

<verify>
    <xsl:copy-of select="dyn:evaluate('/')"/>
</verify>

3.

Пожалуйста, попробуйте еще раз с этим:

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

<xsl:param name="path" select="'/root/charlie'"/>

<xsl:template match="/">
    <results>
        <processor>
            <xsl:value-of select="system-property('xsl:vendor')"/> 
        </processor>
        <support>
            <xsl:value-of select="function-available('dyn:evaluate')"/>
        </support>
        <path>
            <xsl:value-of select="$path"/>
        </path> 
        <eval-param>
            <xsl:copy-of select="dyn:evaluate($path)"/>
        </eval-param>   
        <eval-string>
            <xsl:copy-of select="dyn:evaluate('/root/charlie')"/>
        </eval-string>  
        <copy>
            <xsl:copy-of select="/root/charlie"/>
        </copy> 
    </results>
</xsl:template>

</xsl:stylesheet>
Другие вопросы по тегам