获取exsl:node-set在PHP中工作

geo*_*lee 9 php xml xslt exslt

我有以下PHP代码,但它不起作用.我没有看到任何错误,但也许我只是失明.我在PHP 5.3.1上运行它.

<?php
$xsl_string = <<<HEREDOC
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exsl="http://exslt.org/common"
                extension-element-prefixes="exsl">
  <xsl:template match="/">
    <p>Hello world</p>
    <xsl:variable name="person">
      <firstname>Foo</firstname>
      <lastname>Bar</lastname>
      <email>test@example.com</email>
    </xsl:variable>
    <xsl:value-of select="exsl:node-set(\$person)/email"/>
  </xsl:template>
</xsl:stylesheet>
HEREDOC;

$xml_dom = new DOMDocument("1.0", "utf-8");
$xml_dom->appendChild($xml_dom->createElement("dummy"));

$xsl_dom = new DOMDocument();
$xsl_dom->loadXML($xsl_string);

$xsl_processor = new XSLTProcessor();
$xsl_processor->importStyleSheet($xsl_dom);
echo $xsl_processor->transformToXML($xml_dom);
?>
Run Code Online (Sandbox Code Playgroud)

此代码应输出"Hello world",然后输出"test@example.com",但不会显示电子邮件部分.知道什么是错的吗?

-Geoffrey Lee

Dim*_*hev 8

问题是提供的XSLT代码具有默认命名空间.

因此,<firstname>,<lastname><email>元件在XHTML命名空间.但是email在没有任何前缀的情况下引用:

exsl:node-set($person)/email
Run Code Online (Sandbox Code Playgroud)

XPath认为所有未加前缀的名称都在"无名称空间"中.它试图在"无命名空间"中找到exsl:node-set($person)被调用的子email节点,但这是不成功的,因为它的email子节点位于xhtml命名空间中.因此,没有email选择和输出节点.

方案:

这种转变:

<xsl:stylesheet version="1.0"
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:x="http://www.w3.org/1999/xhtml"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="exsl x">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
    <html>
     <p>Hello world</p>
     <xsl:variable name="person">
      <firstname>Foo</firstname>
      <lastname>Bar</lastname>
      <email>test@example.com</email>
     </xsl:variable>
     <xsl:text>&#xA;</xsl:text>
     <xsl:value-of select="exsl:node-set($person)/x:email"/>
     <xsl:text>&#xA;</xsl:text>
    </html>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于任何XML文档(未使用)时,产生想要的结果:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:x="http://www.w3.org/1999/xhtml">
   <p>Hello world</p>
test@example.com
</html>
Run Code Online (Sandbox Code Playgroud)

请注意:

  1. 添加的名称空间定义带有前缀 x

  2. 更改的select属性<xsl:value-of>:

exsl:node-set($person)/x:email