使用 XSL、PHP、Perl、XML 逼近 MVC。

Posted

技术标签:

【中文标题】使用 XSL、PHP、Perl、XML 逼近 MVC。【英文标题】:Approximating an MVC using XSL, PHP, Perl, XML. 【发布时间】:2012-11-28 22:43:59 【问题描述】:

问题:我有一个存储在数据库中的 XML sn-p,我想将它与数据库中的其他几个字段结合起来,并使用 php 中的 html 来呈现它们。

我的解决方案: 我有 Perl 后端脚本

$query = "select id, description, xml_content, name from table where id = '$id'";

然后修改 XML 以包含这些字段。

$xml_content =~ s|<Record>|<Record name="$name" id="$id" desc="$desc">|i;

然后我使用 XSL 文件将其转换为

  <xsl:output method="html"/>

  <xsl:template match="/">
   <html xmlns="http://www.w3.org/1999/xhtml">
      <body>
        <form action="info.php" method="get" accept-charset="utf-8">
          <label for="id">Display xml for: </label>
          <input type="text" name="id" value="" id="id" size="40"/>
            <p><input type="submit" value="Display it! &#x02192;"/></p>
            </form>
            <xsl:apply-templates/>
      </body>
   </html>
  </xsl:template>

  <xsl:template match="doc:Record">
    <p>
      <xsl:choose>
        <xsl:when test="./@none">
          XML Content ID <xsl:value-of select="@id"/> NOT FOUND 
        </xsl:when>
        <xsl:otherwise>
          XML Content ID <xsl:value-of select="@id"/> Found  
         <xsl:value-of select="@desc"/> - <xsl:value-of select="@name"/> 
      </xsl:otherwise>
      </xsl:choose>
    </p>
  </xsl:template>

然后我使用 PHP 获取 CGI 变量并运行 perl 脚本并显示输出。

<?php 
if (!empty($_GET['id'])) 
    $command = "getxml.pl --id=" . $_GET['id'];
    $process = proc_open($command, $descriptorspec, $pipes, null, $_SERVER);
    if (is_resource($process))  
        $line = stream_get_contents($pipes[1]);
     else  
        $line = '<Record none="" desc="' . $command . '"></Record>';
    


header('Content-type: text/xml');
echo '<?xml version="1.0" encoding="ISO-8859-1"?>';
echo '<?xml-stylesheet type="text/xsl" href="xmlinfo.xsl"?>';
echo "\n";

if (empty($command))  
    #Display the form only.
    $line = '<Record></Record >';

echo "$line \n";

?>

由于 PHP 没有配置 xslt,这是我能想到的唯一使用 PHP 在 HTML 中显示 XML 的方法。

我的问题是:

    有没有办法删除XSL 中的&lt;html&gt;&lt;body&gt;&lt;form&gt; 部分并将其放入PHP 中。这样看起来会干净得多。

谢谢。

【问题讨论】:

这是一个非常疯狂的工作流程!请问,这个过程的哪些部分是重要的?你能用一个网络框架重新实现整个事情吗?如果你给出一个示例 XML 文档,我可以用 Perl 模拟一些东西,尽管我确信 RoR(甚至可能是 PHP)也会有办法做到这一点。最后的回报也应该是 HTML 或 XML(我真的在问标题)。也许你也可以给出一个示例响应。 嗯,主要的是我想在浏览器中显示一些信息(我猜这意味着 HTML 作为最终输出)来自存储在数据库中的一大块 XML 以及来自其他一些信息的其他信息数据库中的表。最大和最重要的部分是存储在 XML 中,所以我从那里开始。 我想尽可能多地保留 XML。我决定抓住所有其他位并将其转换/嵌入到大 XML 块中。这就是 Perl 部分。然后我考虑使用相同的 Perl 脚本来执行 CGI 部分,但决定使用 PHP 进行调用会更“干净(??)”。这样我也可以使用 cli 中的 Perl 脚本。这就是我最终使用 XML、XSL、Perl 和 PHP 的原因。相当愚蠢的解决方案,而且不太优雅 当我编写一个示例时,您可以在我的一篇旧博客文章中看到我要去哪里:blogs.perl.org/users/joel_berger/2012/10/… 【参考方案1】:

这是一个使用实际框架的示例。我使用的框架是Mojolicious for Perl,当然其他人也可以处理这个问题。我设置了几种数据库处理方法(您可以从原始脚本中调整)。然后我使用内置的 XML 解析器来更新记录的属性。

最后我设置了两条路线。如果您访问/,则运行时会按要求获得您的页面。请注意,XML 已被转义(在模板中),以便将其作为文本呈现给浏览器。如果您更喜欢其他形式的显示,则可以更改此设置。如果您访问/record?id=1,您将直接获得 XML 结果。这对于 RESTful 接口更有用。

假设您将其命名为 app.pl。要运行它,您可以简单地

./app.pl daemon

然后访问 http://localhost:3000 以使用 mojo 的内置服务器之一进行查看(是的,它也可以在 CGI 下运行)。

或者您可以实际与脚本进行交互。假设您只想在命令行中查看一条记录

./app.pl get '/record?id=1'

或者你想插入一些东西,helpers 可以通过eval获得

./app.pl eval 'app->insert(2, "Something", "<Record>Something Else</Record>", "Name")'

很酷吧?

#!/usr/bin/env perl

use Mojolicious::Lite;
use Mojo::DOM;
use DBI;

# connect to database
use DBI;

helper db => sub  
  state $dbh = DBI->connect("dbi:SQLite:database.db","","") or die "Could not connect";
;

# add helper methods for interacting with database
helper create_table => sub 
  my $self = shift;
  warn "Creating table 'records'\n";
  $self->db->do('CREATE TABLE records (id INT, description TEXT, xml_content TEXT, name VARCHAR(255));');
  $self->insert(1,'Description','<Record>Contents</Record>','Name');
;

helper select => sub 
  my $self = shift;
  my $sth = eval  $self->db->prepare('SELECT * FROM records WHERE id = ?')  || return undef;
  my $id = shift or return 0;
  $sth->execute($id);
  return $sth->fetchrow_hashref;
;

helper insert => sub 
  my $self = shift;
  my ($id, $description, $xml, $name) = @_;
  my $sth = eval  $self->db->prepare('INSERT INTO records VALUES (?,?,?,?)')  || return undef;
  $sth->execute($id, $description, $xml, $name);
  return 1;
;

# if statement didn't prepare, assume its because the table doesn't exist
defined app->select or app->create_table;

helper 'xml_by_id' => sub 
  my $self = shift;
  my $id = shift;

  my $row = $self->select($id) || ;
  return '<Record></Record>' unless keys %$row;

  my $xml = Mojo::DOM->new->xml(1)->parse( $row->xml_content );
  my $record = $xml->at('Record');

  for my $key ( qw/ name id description / ) 
    $record->$key = $row->$key;
  

  return wantarray ? ($xml, $row) : $xml;
;

any '/record' => sub 
  my $self = shift;
  my $id = $self->param('id') || $self->render_not_found;
  my $xml = $self->xml_by_id($id);
  $self->render( text => $xml, format => 'xml' );
;

any '/' => sub 
  my $self = shift;

  if ( my $id = $self->param('id') ) 
    my ($xml, $row) = $self->xml_by_id($id);
    $self->stash( id  => $id  );
    $self->stash( xml => $xml );
    $self->stash( row => $row );
  

  $self->render('index');
;

app->start;

__DATA__

@@ index.html.ep
<!DOCTYPE html>
<html>
<head><title>Get XML</title></head>
<body>
  <form action="/" method="get" accept-charset="utf-8">
    <label for="id">Display xml for: </label>
    <input type="text" name="id" value="" id="id" size="40"/>
    <p><input type="submit" value="Display it! &#x02192;"/></p>
  </form>
  % if ( my $id = stash('id') ) 
    <p> XML Content ID <%= $id %>
      % my $row = stash('row');
      % if ( keys %$row ) 
        Found
        <%= $row->description %> - <%= $row->name %> 
      % else 
        NOT FOUND
      %
    </p>
    %= stash('xml')
  % 
</body>
</html>

【讨论】:

以上是关于使用 XSL、PHP、Perl、XML 逼近 MVC。的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC 与 XSL

我应该为这个项目使用 Perl 还是 PHP 或其他东西?

使用 XSL 打印 XML 树

链接 XSL 和 XML?`

使用 XSL 将 json 转换为 XML

xml用xsl实现分类排版的问题