出于某种原因,当通过 dyn:evaluate() 在 XSLT 中执行时,我的 XPath 查询不起作用。我正在使用 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" />
Where$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 扩展)。我错过了什么?
编辑
我的实际脚本在几个类和文件夹中,所以我发布了我正在运行的更简单的版本。即使 Notepad++ 告诉我应该这样做,它的 dyn:evaluate() 仍然不起作用,并且我只是将其他类中的函数复制粘贴到一个中以便于参考。
我的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是处理器。它使用 PHP 中的 XMLReader 和 XSLTProcessor 类。
<?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>
失败部分是目标是一个空元素。