让 exsl:node-set 在 PHP 中工作

发布于 2024-09-03 12:46:01 字数 1473 浏览 5 评论 0原文

我有以下 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>[email protected]</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);
?>

此代码应输出“Hello world”,后跟“[email protected]” ,但电子邮件部分不会出现。知道出了什么问题吗?

——杰弗里·李

I have the following PHP code, but it's not working. I don't see any errors, but maybe I'm just blind. I'm running this on 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>[email protected]</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);
?>

This code should output "Hello world" followed by "[email protected]", but the e-mail portion doesn't appear. Any idea what's wrong?

-Geoffrey Lee

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云胡 2024-09-10 12:46:01

问题在于提供的 XSLT 代码具有默认命名空间。

因此, 元素位于 xhtml 命名空间中。但是 email 的引用没有任何前缀:

exsl:node-set($person)/电子邮件

XPath 认为所有无前缀的名称都位于“无命名空间”中。它尝试查找位于“无命名空间”中的名为 emailexsl:node-set($person) 子级,但这是不成功的,因为它的 email child 位于 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>[email protected]</email>
     </xsl:variable>
     <xsl:text>
</xsl:text>
     <xsl:value-of select="exsl:node-set($person)/x:email"/>
     <xsl:text>
</xsl:text>
    </html>
  </xsl:template>
</xsl:stylesheet>

当应用于任何 XML 文档(未使用)时,会产生所需的结果

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:x="http://www.w3.org/1999/xhtml">
   <p>Hello world</p>
[email protected]
</html>

请注意

  1. 添加的带有前缀 x

    的命名空间定义

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

exsl:node-设置($person)/x:电子邮件

The problem is that the provided XSLT code has a default namespace.

Therefore, the <firstname> , <lastname> and <email> elements are in the xhtml namespace. But email is referenced without any prefix in:

exsl:node-set($person)/email

XPath considers all unprefixed names to be in "no namespace". It tries to find a child of exsl:node-set($person) called email that is in "no namespace" and this is unsuccessful, because its email child is in the xhtml namespace. Thus no email node is selected and output.

Solution:

This transformation:

<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>[email protected]</email>
     </xsl:variable>
     <xsl:text>
</xsl:text>
     <xsl:value-of select="exsl:node-set($person)/x:email"/>
     <xsl:text>
</xsl:text>
    </html>
  </xsl:template>
</xsl:stylesheet>

when applied on any XML document (not used), produces the wanted result:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:x="http://www.w3.org/1999/xhtml">
   <p>Hello world</p>
[email protected]
</html>

Do note:

  1. The added namespace definition with prefix x

  2. The changed select attribute of <xsl:value-of>:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文