1

何らかの理由で、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>

失敗した部分はターゲットが空の要素です。

4

1 に答える 1

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:evaluate() が機能しないか、パラメータを渡す方法に問題があります。これは、テストにもう 1 つの要素を追加することで判断できます。

<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>
于 2015-03-08T05:56:28.393 に答える