何らかの理由で、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
ます)。
エラーが返されません。実際、 a を実行すると!に<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:evaluate() は、メモ帳 ++ がそうすべきだと言っているにもかかわらず、まだ機能しないという点で同等であり、参照しやすいように他のクラスの関数を 1 つにコピーアンドペーストしました。
私のmock.xmlは、解析しているスクリプトです
<getListValues>
<node>
<Assignee>Assginee Value</Assignee>
<Summary>Summary Value</Summary>
<Incident_Number>Incident_Number Value</Incident_Number>
</node>
私のcountFieldValues.xml
スタイルシートは、readSubtree php 関数呼び出しで一度に個々のサブツリーを解析するために 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()
ノードセットを返すいくつかの式を見つけました。しかし、彼らは少し奇妙です。
それらが true と評価される場合は次のとおりです。
Assignee
Summary
Incident Number
*[name()="Assignee"]
*[name()="Assignee" and text()="Assignee Value"]
しかし、これらは false と評価されます。
*[Assignee="Assignee Value"]
//Assignee
どうしたんだ...?
アップデート:
Michael の提案で、私は彼のテストを実行し、次の結果を得ました。
<?xml version="1.0" encoding="UTF-8"?>
<results>
<processor>libxslt</processor>
<support>true</processor>
<path>/root/bravo</path>
<target/>
</results>
失敗した部分はターゲットが空の要素です。