【问题标题】:Using XSLT document() on a dynamicly generated XML in PHP在 PHP 中动态生成的 XML 上使用 XSLT document()
【发布时间】:2011-04-26 08:51:08
【问题描述】:

在我的 XSLT 文件中。我使用document()函数

<xsl:variable name="Publicity" select="document('./publicity.xml')" />

这可行,但如果我尝试链接动态生成 XML 的 PHP 脚本,

<xsl:variable name="Publicity" select="document('./publicity.php')" />

我得到一个

Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: file:///C:/wamp/www/XSLT/test.php:3: parser error : Start tag expected, '<' not found in ... on line ...

其中包含来自&lt;?php&lt;

看起来 XSLTProcessor 没有像通过 HTTP 请求那样请求文件,所以它不是由 Apache / PHP 执行的。

我知道我可以简单地将那个 XML 结构包含到我的主要 XML 中,但我试图避免这种情况......直到有人告诉我没有其他方法。

谢谢!

【问题讨论】:

  • 一点都不清楚。您的源 xml 文档是什么(请提供一个最小示例)。您的 XSLT 样式表是什么(请提供一个最小示例)。 “如果我尝试链接动态生成 XML 的 PHP 脚本”是什么意思?示例必须完整但最少,并且必须重现问题。
  • @Dimitre:当我使用document() 指向XML 文件时,它可以工作,但如果我使用document() 访问PHP 脚本(PHP 可以生成XML 仅供参考)我得到一个错误。比尔说document() 从磁盘读取文件所以PHP 没有执行所以我得到一个错误。我想没有办法真正做到这一点。
  • 查看我的答案以获得解释和解决方法。

标签: php xml xslt


【解决方案1】:

正确的 document() 函数只是从磁盘读取文件,它不会发出 HTTP 请求。所以 PHP 没有执行。

您必须使用 URL 而不仅仅是文件名作为 document() 函数的参数。

<xsl:variable name="Publicity" 
     select="document('http://example.com/publicity.php')" />

我相信以这种方式使用 URL 是大多数 XSLT 处理器中的常见功能,但我没有使用 PHP 对其进行测试,因此您的里程可能会有所不同。

【讨论】:

  • 嗯,由于未知原因,它不适用于 PHP。页面只是超时。我没有对 URL 犯任何错误。我猜它只是不能在 PHP / XSLTProcessor 中完成。不过还是谢谢
  • 然后您可能需要将 PHP 脚本作为离线任务运行以定期创建 XML 文件,以便您的 XSLT 脚本可以读取它。抱歉,你不能从这里到达那里。 :)
【解决方案2】:

由于我在寻找类似问题的解决方案时,在著名搜索引擎的帮助下偶然发现了这篇文章,所以到目前为止我发现了以下内容。我的目标是拥有一个包含一些 XHTML 布局的 layout.xml 文件,并用 PHP 生成的 data.xml 树中的数据(但未保存到磁盘)通过 XSL 转换填充它。

如果不将动态生成的 XML 保存在磁盘上或将其包含在 XSL 树中,您似乎无法直接在 XSLT 文件中导入它。一个解决方案似乎是在你的 data.xml 上使用两个 xsl 转换:

  1. 通过 php 生成包含数据的 data.xml。
  2. 然后使用 XSL 转换生成一个 XML,将您的 data.xml 转换为 data.xsl(第一次转换) - data.xsl 需要如此结构化,以便根据需要将其数据应用到 layout.xml(请参阅下一步)
  3. 在您的 layout.xml 中使用该 data.xsl 来填充数据(第二次转换)。

可以在此处找到更详细描述该内容的博文 [虽然是德语]:xsl als Templatesystem

这可能有点作弊,因为您的 data.xsl 是原始 XSL 的变体,其中包含数据结构。但是,它似乎更优雅,因为您可能可以创建一个通用的 first-transformation-xsl 文件(只需将其保存到磁盘一次)并重新使用它。我还不知道是否还有优化的空间,因为到目前为止我还没有过多地使用 XSLT。

【讨论】:

    【解决方案3】:

    我通过简单地使用 CURL 获取 XML(静态或动态)来使用 xslt document() 函数和 php 取得成功。所以我的 URL 是一个 PHP 脚本(代理),它在某处 CURLs 一个 XML 资源。像这样获取 RSS 格式的 XML 文档

    <xsl:variable name="homeUrl" select="http://mydomain.tld/"/>
    <xsl:variable name="xmlUrl" select="http://domain.tld/feed.rss"/>
    <xsl:variable name="includeXML" select="document(concat($homeUrl,'api/proxy.php?url=',$xmlUrl))"/>
    
    <xsl:for-each select="$includeXML/rss/channel/item">
        ...
    

    【讨论】:

    • 谢谢!我会做一些测试,看看它是否适合我。
    【解决方案4】:

    如果 the document() 函数的第一个参数是一个相对 URI,它会从第二个参数的 base-uri 解析。如果没有第二个参数,则使用包含对 document() 函数的调用的 XSLT 样式表的基本 URI。

    这是W3C XSLT spec的摘录。:

    "URI 引用可能是相对的。 的基本 URI(参见 [3.2 基本 URI]) 第二个参数中的节点 文档中第一个节点集 order 用作基本 URI 将相对 URI 解析为 绝对 URI。如果第二个参数 被省略,则默认为 样式表中包含的节点 包含调用的表达式 到文档功能。请注意,一个 零长度 URI 引用是 参考相关文件 URI 引用是哪个 解决;因此 document("") 指 样式表的根节点;这 样式表的树表示 与 XML 完全相同 包含样式表的文档是 初始源文档。”

    当 XSLT 样式表确实有 URI(文件 url 或 http url)时,这很有效。但是,动态生成的样式表在内存中并且没有基本 URI。在这种情况下,作为document() 函数的第一个也是唯一一个参数的相对 URI 无法成功解析。

    解决方案是提供 XML 文档的完整(绝对)URI

    【讨论】:

    • 我的解决方案是什么?谢谢
    • @Cybrix:正如我所说:“解决方案是提供 XML 文档的完整(绝对)URI”。
    • 我明白了。但这就是 Bill Karwin 的建议,不幸的是 PHP 的 XSLTProcessor 无法进行转换。不过还是谢谢你的回答。
    • @Cybrix:如果您可以在单独的问题中提供使用 document() 函数的情况,我相信使用 avsolute-URL 参数,PHP 的 XSLT 处理器“不能”。也许还有别的东西......
    猜你喜欢
    • 1970-01-01
    • 2011-03-24
    • 2012-11-10
    • 1970-01-01
    • 2014-08-17
    • 2010-09-24
    • 2010-10-03
    • 2012-05-23
    相关资源
    最近更新 更多