php xml and access (200分噢!)(200分)

  • 主题发起人 主题发起人 michen
  • 开始时间 开始时间
M

michen

Unregistered / Unconfirmed
GUEST, unregistred user!
我是菜鸟,问的问题好象很多:) 就把我所有的分数送了吧:)
哪位高手大侠帮帮我啊,thanks!
我的主页cool.aa88.net (NT server)原来是用asp+access做的
现在拿到了一台新的服务器,是freebsd+php (have no mysql[:(])
我的问题是:php可以用access吗?(除了odbc_connect,freebsd上没装数据源)
或者有什么好的办法能直接对一个xml文档进行操作(做资料收集网站用)
当然最好是在服务器端解析,将完成之后的html文件送回客户端
(我把access的数据文件转成了xml格式,好大,不可能让人下载到客户端再生成html
那样来访者会疯掉的:P
顺便问一下,xls中变量的使用,我可不可以从php中传送一个变量给xls?怎么做?
 
php对xml的操作已经搞定了,不过不是很完美,只能取出部份资料,用起来不是很方便
我把找到(我改动过一点点)的class贴到这里,希望对有同样问题的朋友有所帮助
另外,php到底是否可以用access丫?除了odbc_connect,和COM(unix上都不支持)
代码:
<?php 
/* 
   (c) 2000 Hans Anderson Corporation.  All Rights Reserved. 
   You are free to use and modify this class under the same 
   guidelines found in the PHP License. 
   ----------- 
   bugs/me: 
   http://www.hansanderson.com/php/ 
   me@hansanderson.com 
   ----------- 
   Version 1.0 
       - 1.0 is the first actual release of the class.  It's  
         finally what I was hoping it would be, though there 
         are likely to still be some bugs in it.  This is 
         a much changed version, and if you havedo
wnloaded 
         a previous version, this WON'T work with your existing 
         scripts!  You'll need to make some SIMPLE changes. 
       - .92 fixed bug that didn't include tag attributes 
         (to use attributes, add _attributes[array_index] 
          to the end of the tag in question: 
           $xml_html_head_body_img would become 
           $xml_html_head_body_img_attributes[0],  
          for example) 
          -- Thanks to Nick Winfield <nick@wirestation.co.uk> 
             for reporting this bug. 
       - .91 No Longer requires PHP4! 
       - .91 now all elements are array.  Using objects has 
         been discontinued. 
   ----------- 
   What class.xml.php is: 
   A very, very easy to use XML parser class. It uses PHP's XML functions 
   for you, returning one array that has all the tag information.  The only  
   hard part is figuring out the syntax of the tags! 
   ----------- 
   Sample use: 
   require('class.xml.php');
   $file = "data.xml";
   $data = implode("",file($file)) or die("could not open XML input file");
   $obj = new xml($data,"xml");

   print $xml["hans"][0]->num_results[0];
   for($i=0;$i<sizeof($xml["hans"]);$i++) { 
    print $xml["hans"][$i]->tag[0] . " ";
   } 
   To print url attributes (if they exist): 
   print $xml["hans"][0]->attributes[0]["size"];
# where "size" was an attr name 
   (that's it! slick, huh?) 
   ----------- 
   Two ways to call xml class:  
       $xml = new xml($data);
       - or - 
       $xml = new xml($data,"jellyfish");

   The second argument (jellyfish) is optional.  Default is 'xml'. 
   All the second argumentdo
es is give you a chance to name the array 
   that is returned something besides "xml" (in case you are already using 
   that name).  Normal PHP variable name rules apply. 
   ---------- 
   Explanation of xml class: 
   This class takes valid XML data as an argument and  
   returns all the information in a complex but loopable array. 
   Here's how it works: 
       Data: 
           <html> 
            <head> 
             <title>Hans Anderson's XML Class</title> 
            </head> 
            <body> 
            </body> 
           </html> 
       Run the data through my class, then
 access the title like this: 
       $xml["html_head"][0]->title[0];

       Or, loop through them: 
       for($i=0;$i<sizeof($xml["html_head"]);$i++) { 
           print $xml["html_head"][$i]->title[0] . " ";
       } 
       Yes, the variable names *are* long and messy, but it's 
       the best way to create the tree, IMO. 

Here is a complex explanation I sent to one class.xml.php user: 
--------- 
> Now I've run into another problem: 
> 
> <STORY TIMESTAMP="2000-12-15T20:08:00,0"> 
> <SECTION>Markets</SECTION> 
> <BYLINE>By <BYLINE_AUTHOR ID="378">Aaron L. Task</BYLINE_AUTHOR><BR/>Senior 
> Writer</BYLINE> 
> </STORY> 
> 
> Howdo
 I get BYLINE_AUTHOR? 
print $xml["STORY_BYLINE"][0]->BYLINE_AUTHOR[0];

> And just a little question: Is there an easy way to get TIMESTAMP? 
print $xml["STORY"][0]->attributes[0]["TIMESTAMP"];

This is confusing, I know, but it's the only way I could reallydo
 
this.  Here's the rundown: 
The $xml part is an array -- an array of arrays.  The first array is the
name of the tag -- in the first case above, this is the tag STORY, and 
below that BYLINE.  You want BYLINE_AUTHOR.  You want the first BA.  The 
first one is index [0] in the second part of the two-dimensional array. 
Even if there is only *one* byline author, it's still an array, and you 
still have to use the [0].  Now, the two-dimensional array is storing 
dynamic structures -- objects in this case.  So, we need to dereference 
the object, hence the ->.  The BYLINE_AUTHOR is the tag you want, and it 
is an array in that object.  The reason for the array is that if there are 
more than one BYLINE_AUTHOR for the tags STORY, BYLINE, we would have a 
[0] and [1] in the array.  In your case there is just the one. 
*** This is very confusing, I know, but once you understand it, the power 
of this method will be more apparent.  You have access to *every* bit of 
information in the XML file, without having todo
 anything but understand 
how to refer to the variables. *** 
EVERY variable will look like this: 
       print $xml["STORY_BYLINE"][0]->BYLINE_AUTHOR[0];

The trick is understanding how to get the variable to give you the 
information.  This is an array of arrays of objects holding arrays! 
Any tag that has attributes will have them stored in a special object 
array named "attributes" and will be called this way: 
       print $xml["STORY"][0]->attributes[0]["TIMESTAMP"];

If you aren't sure if there are attributes, you coulddo
 isset() or 
is_array() for that above example.  If isset(), you could for loop and 
while(list($k,$v) = each($xml...)) over it to get the values. 

         array of 
                 objects 
                    | 
                    | 
$xml["STORY_BYLINE"][0]->BYLINE_AUTHOR[0];
          ^                    ^ 
       array of                ^ 
        arrays                 ^ 
                               ^ 
                            array in 
                             object 
In general, to get the value of this: 
<STATE> 
       <STATENAME></STATENAME> 
       <COUNTY> 
               <COUNTYNAME></COUNTYNAME> 
               <CITY></CITY> 
               <CITY></CITY> 
       </COUNTY> 
       <COUNTY> 
               <COUNTYNAME></COUNTYNAME> 
               <CITY></CITY> 
               <CITY></CITY> 
       </COUNTY> 
</STATE> 
You would look for what you want, say "CITY", then
 go UP one level, to 
COUNTY (COUNTYNAME is on the same 'level'), for your first array: 
$xml["STATE_COUNTY"] -- ALL tags pushed together are separated with 
"_".  Otherwise tags are as they were -- spaces, dashes, CaSe, etc. 
Now, you want the first COUNTY, though there are two, so we aredo
 this: 
$xml["STATE_COUNTY"][0] -- to get the second, we'd use [1] instead of 
[0].  You could alsodo
 a for() loop through it, using sizeof() to figure 
out how big it is. 
So, we have the STATE,COUNTY we want -- the first one.  It's an 
object, and we know we want the CITY.  So, we dereference the object.  The 
name of the array we want is, of course, CITY: 
$xml["STATE_COUNTY"][0]->CITY[0] (the first one, the second one would be 
[1]). 
And that's it.  Basically, find what you want, and go up a level. 
You coulddo
 some complex for loops to go through them all, too: 
for($i=0;$i<sizeof($xml["STATE_COUNTY"]);$i++) { 
       for($j=0;$j<sizeof($xml["STATE_COUNTY"][0]->CITY);$j++) { 
               print $xml["STATE_COUNTY"][$i]->CITY[$j];

       } 
} 
----------- 
Whew.  I hope that helps, not hurts. 

*/ 
/* used to store the parsed information */ 
class xml_container { 
   function store($k,$v) { 
       $this->{$k}[] = $v;
   } 
} 
/* parses the information */ 
class xml {  
   // initialize some variables 
   var $current_tag=array();
   var $xml_parser;
   var $Version = 1.0;
   var $tagtracker = array();
   /* Here are the XML functions needed by expat */ 
   /* when expat hits an opening tag, it fires up this function */ 
   function startElement($parser, $name, $attrs) { 
       array_push($this->current_tag, $name);
// add tag to the cur. tag array 
       $curtag = implode("_",$this->current_tag);
// piece together tag 
       /* this tracks what array index we are on for this tag */ 
       if(isset($this->tagtracker["$curtag"])) { 
           $this->tagtracker["$curtag"]++;
       } else
 { 
           $this->tagtracker["$curtag"]=0;
       } 

       /* if there are attributes for this tag, we set them here. */ 
       if(count($attrs)>0) { 
           $j = $this->tagtracker["$curtag"];
           if(!$j) $j = 0;

           if(!is_object($GLOBALS[$this->identifier]["$curtag"][$j])) { 
               $GLOBALS[$this->identifier]["$curtag"][$j] = new xml_container;
           } 
           $GLOBALS[$this->identifier]["$curtag"][$j]->store("attributes",$attrs);
               } 
   } // end function startElement 

   /* when expat hits a closing tag, it fires up this function */ 
   function endElement($parser, $name) { 
       $curtag = implode("_",$this->current_tag);
    // piece together tag 
                               // before we pop it off, 
                               // so we can get the correct 
                               // cdata 
       if(!$this->tagdata["$curtag"]) { 
           $popped = array_pop($this->current_tag);
// or else
 we screw up where we are 
           return;
    // if we have no data for the tag 
       } else
 { 
           $TD = $this->tagdata["$curtag"];
           unset($this->tagdata["$curtag"]);
       } 
       $popped = array_pop($this->current_tag);
                               // we want the tag name for 
                               // the tag above this, it  
                               // allows us to group the 
                               // tags together in a more 
                               // intuitive way. 
       if(sizeof($this->current_tag) == 0) return;
    // if we aren't in a tag 
       $curtag = implode("_",$this->current_tag);
    // piece together tag 
                               // this time for the arrays 
       $j = $this->tagtracker["$curtag"];
       if(!$j) $j = 0;

       if(!is_object($GLOBALS[$this->identifier]["$curtag"][$j])) { 
           $GLOBALS[$this->identifier]["$curtag"][$j] = new xml_container;
       } 
       $GLOBALS[$this->identifier]["$curtag"][$j]->store($name,$TD);
#$this->tagdata["$curtag"]);
       unset($TD);
       return TRUE;
   } 

   /* when expat finds some internal tag character data, 
      it fires up this function */ 
   function characterData($parser, $cdata) { 
       $curtag = implode("_",$this->current_tag);
// piece together tag         
       $this->tagdata["$curtag"] .= $cdata;
   } 
   /* this is the constructor: automatically called when the class is initialized */ 
   function xml($data,$identifier='xml') {   
       $this->identifier = $identifier;

       // create parser object 
       $this->xml_parser = xml_parser_create();

       // set up some options and handlers 
       xml_set_object($this->xml_parser,&amp;$this);
       xml_parser_set_option($this->xml_parser,XML_OPTION_CASE_FOLDING,0);
       xml_set_element_handler($this->xml_parser, "startElement", "endElement");
       xml_set_character_data_handler($this->xml_parser, "characterData");

       if (!xml_parse($this->xml_parser, $data, TRUE)) { 
           sprintf("XML error: %s at line %d", 
           xml_error_string(xml_get_error_code($this->xml_parser)), 
           xml_get_current_line_number($this->xml_parser));
       } 
       // we aredo
ne with the parser, so let's free it 
       xml_parser_free($this->xml_parser);
       }  // end constructor: function xml() 

} // thus, we end our class xml 
?>
调用的例子:
代码:
<?php
require('class.xml.php');
$file = "data.xml";
$data = implode("",file($file)) or die("could not open XML input file");
$obj = new xml($data,"xml");

print $xml["root_data"][0]->num_results[0];
for($i=0;$i<sizeof($xml["root_data"]);$i++) { 
	print $xml["root_data"][$i]->data_title[0] . "<br>";
}
?>
 
php用ODBC连接ACCESS数据库
具体我没用过,不清楚。
 
要设置dsn。建议下载ADODB,一切搞定。
http://php.weblogs.com/adodb
 
007pig兄,能说得详细一点吗?
服务器的环境是freeBSD+php4
我只有一个主页空间的ftp,无法操作服务器
 
Access 数据库必须在Windows的服务器上。以下是使用odbc_connect的例子:
<html>
<head>
<title>My First PHP Script With DB Support!</title>
</head>
<body bgcolor=#808080>
<center>
<table width=80% border=3 bgcolor=#cccccc>
<tr><td>
这个例程简单演示了 php 通过 odbc 访问数据库.
只需要通过 控制面板->ODBC 数据源->添加数据源(WebTest)即可.
</td></tr>
</table>
<form method=post action="<? echo getenv("REDIRECT_URL");
?>">
<table border=3 width=80% cols=2 bgcolor=#cccccc>
<tr><td colspan=2>操作</td></tr>
<tr><td align=center>
<table width=100% border=0>
<tr><td>编号</td><td><input type=text name="n">(数字)</td></tr>
<tr><td>名称</td><td><input type=text name="name" maxlength=40>(字符串
)</td></tr>
<tr><td colspan=2>
<input type=submit name="verb" value="Insert">
<input type=submit name="verb" value="Delete">
<input type=submit name="verb" value="Update">
<input type=reset value="Reset">
</td></tr>
</table>
</td>
<td align=center>
<input type=submit name="verb" value="Create Table">

<input type=submit name="verb" value="Drop Table">
</td></tr>
</table>
</form>
<?
if($con_id = odbc_connect("WebTest","ABC","123",SQL_CUR_USE_ODBC)){
$n = (int) $n;

if(strcmp($verb,"")!=0){
if(strcmp($verb,"Create Table")==0){
$sql_string = "create table testtb (n integer, name char(40))";

$err_msg = "创建数据表时出错, 该表已经存在?";
}else
if(strcmp($verb, "Drop Table")==0){
$sql_string = "drop table testtb";
$err_msg = "Drop数据表时出错, 该表不存在?";
}else
if(strcmp($verb,"Insert")==0){
$sql_string = "insert into testtb values ($n,'$name')";
$err_msg = "添加新记录时出错, 请检查您填写的数据.";
}else
if(strcmp($verb,"Delete")==0){
$sql_string = "delete from testtb where n = $n";
$err_msg = "删除记录时出错, 请检查您填写的数据.";
}else
if(strcmp( $verb,"Update")==0){
$sql_string = "update testtb set name = '$name' where n = $n";
$err_msg = "更新记录时出错, 请检查您填写的数据.";
}
print $sql_string;

if(!odbc_exec($con_id,$sql_string))
echo $err_msg;
}
if($result=odbc_exec($con_id,"select n, name from testtb")){
?>
<hr size=1 width=80%>
<table border=3 width=80% cols=2 bgcolor=#cccccc>
<tr><td colspan=2 align=left>查询结果</td></tr>
<tr><td>编号</td><td>名称</td></tr>
<?
while(odbc_fetch_row($result))
printf( "<tr><td>%d</td><td>%s</td></tr>n",odbc_result($result,1)
,odbc_result($result,2));
?>
</table>
<?
}else

echo "查询失败, 请确认正确数据表存在.";
odbc_close($con_id);
}else

echo "连接数据库失败, 请检查您是否正确的配置了 ODBC 数据源.";
?>
</center>
</body>
</html>
如果数据库只有Mysql,不妨试试 Access-to-Mysql 这个软件:
http://www.convert-in.com/acc2sql.htm
将access的数据转换到Mysql数据库上。
尽量不要使用XML作为数据库,因为PHP对XML的支持还不完善。速度也无法得到保证。
 
谢谢回复,但是我需要的不是win上的连接方法:(
我现在就是想把一个NT主机上的access数据库放到
我的另一个空间freeBSD+php上去用,要不然用perl能连也可以
有办法吗?
thank all
 
好像现在没有Access在FreeBSD下的驱动。
我目前想到的唯一办法是把Access数据库转换为Mysql的。
 
就是惨在这里了:(
我没有mysql的帐号可用,只有php perl
那么如果象我那种资料收集网页cool.aa88.net
如果用文本保存数据,资料多了之后都会有哪些麻烦?
 
文本保存数据,数据的安全性得不到保证。
由于读写文件时要先锁定,后解锁,很麻烦,并且容易造成资料的丢失。
现在文本数据库编写最好的程序是 wdb www.lvxing.net 。它的安全性比较好,可以参考一下。关于XML的数据库存在形式,我目前没有发现任何程序使用。
如果能申请到免费的空间,支持Mysql的,如何?
 
我下载了一个perl调用access的包,可不知道怎么用:((
免费空间不爱用,没准哪天就停了:(
现在手头那个是朋友在北京电信租的,有效期八年:)
xixi
 
那再租个Mysql空间吧。省得那么麻烦
 
接受答案了.
 
后退
顶部