Getting an Undefined offset: 1 error when try the following code that outputs some data to word document...
Using CodeIgniter in the controller I have:
$htmltodoc= new HTML_TO_DOC();
$htmltodoc->createDoc("<h1>Testing data </h1>", "testfile.doc");
In the helper directory I am using the following functions in a class called HTML_TO_DOC below...
class HTML_TO_DOC
{
var $docFile="";
var $title="";
var $htmlHead="";
var $htmlBody="";
/**
* Constructor
*
* @return void
*/
function HTML_TO_DOC()
{
$this->title="Untitled Document";
$this->htmlHead="";
$this->htmlBody="";
}
/**
* Set the document file name
*
* @param String $docfile
*/
function setD开发者_StackOverflow社区ocFileName($docfile)
{
$this->docFile=$docfile;
if(!preg_match("/\.doc$/i",$this->docFile))
$this->docFile.=".doc";
return;
}
function setTitle($title)
{
$this->title=$title;
}
/**
* Return header of MS Doc
*
* @return String
*/
function getHeader()
{
$return = <<<EOH
<html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<meta name=ProgId content=Word.Document>
<meta name=Generator content="Microsoft Word 9">
<meta name=Originator content="Microsoft Word 9">
<!--[if !mso]>
<style>
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<![endif]-->
<title>$this->title</title>
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Print</w:View>
<w:DoNotHyphenateCaps/>
<w:PunctuationKerning/>
<w:DrawingGridHorizontalSpacing>9.35 pt</w:DrawingGridHorizontalSpacing>
<w:DrawingGridVerticalSpacing>9.35 pt</w:DrawingGridVerticalSpacing>
</w:WordDocument>
</xml><![endif]-->
<style>
<!--
/* Font Definitions */
@font-face
{font-family:Verdana;
panose-1:2 11 6 4 3 5 4 4 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:536871559 0 0 0 415 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0in;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:7.5pt;
mso-bidi-font-size:8.0pt;
font-family:"Verdana";
mso-fareast-font-family:"Verdana";}
p.small
{mso-style-parent:"";
margin:0in;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:1.0pt;
mso-bidi-font-size:1.0pt;
font-family:"Verdana";
mso-fareast-font-family:"Verdana";}
@page Section1
{size:8.5in 11.0in;
margin:1.0in 1.25in 1.0in 1.25in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1032">
<o:colormenu v:ext="edit" strokecolor="none"/>
</o:shapedefaults></xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1"/>
</o:shapelayout></xml><![endif]-->
$this->htmlHead
</head>
<body>
EOH;
return $return;
}
/**
* Return Document footer
*
* @return String
*/
function getFotter()
{
return "</body></html>";
}
/**
* Create The MS Word Document from given HTML
*
* @param String $html :: URL Name like http://www.example.com
* @param String $file :: Document File Name
* @param Boolean $download :: Wheather to download the file or save the file
* @return boolean
*/
function createDocFromURL($url,$file,$download=false)
{
if(!preg_match("/^http:/",$url))
$url="http://".$url;
$html=@file_get_contents($url);
return $this->createDoc($html,$file,$download);
}
/**
* Create The MS Word Document from given HTML
*
* @param String $html :: HTML Content or HTML File Name like path/to/html/file.html
* @param String $file :: Document File Name
* @param Boolean $download :: Wheather to download the file or save the file
* @return boolean
*/
function createDoc($html,$file,$download=false)
{
if(is_file($html))
$html=@file_get_contents($html);
$this->_parseHtml($html);
$this->setDocFileName($file);
$doc=$this->getHeader();
$doc.=$this->htmlBody;
$doc.=$this->getFotter();
if($download)
{
@header("Cache-Control: ");// leave blank to avoid IE errors
@header("Pragma: ");// leave blank to avoid IE errors
@header("Content-type: application/octet-stream");
@header("Content-Disposition: attachment; filename=\"$this->docFile\"");
echo $doc;
return true;
}
else
{
return $this->write_file($this->docFile,$doc);
}
}
/**
* Parse the html and remove <head></head> part if present into html
*/
function _parseHtml($html)
{
$html=preg_replace("/<!DOCTYPE((.|\n)*?)>/ims","",$html);
$html=preg_replace("/<script((.|\n)*?)>((.|\n)*?)<\/script>/ims","",$html);
preg_match("/<head>((.|\n)*?)<\/head>/ims",$html,$matches);
$head=$matches[1];
preg_match("/<title>((.|\n)*?)<\/title>/ims",$head,$matches);
$this->title = $matches[1];
$html=preg_replace("/<head>((.|\n)*?)<\/head>/ims","",$html);
$head=preg_replace("/<title>((.|\n)*?)<\/title>/ims","",$head);
$head=preg_replace("/<\/?head>/ims","",$head);
$html=preg_replace("/<\/?body((.|\n)*?)>/ims","",$html);
$this->htmlHead=$head;
$this->htmlBody=$html;
return;
}
/**
* Write the content int file
*
* @param String $file :: File name to be save
* @param String $content :: Content to be write
* @param [Optional] String $mode :: Write Mode
* @return void
* @access boolean True on success else false
*/
function write_file($file,$content,$mode="w")
{
$fp=@fopen($file,$mode);
if(!is_resource($fp))
return false;
fwrite($fp,$content);
fclose($fp);
return true;
}
}
It will be great if someone can please help me solve this error.. thanks alot.. PS
Undefined offset: 1
means you are trying to read an array key '1' when there is none. That would probably mean the line you are getting it is here:
$head=$matches[1];
or
$this->title = $matches[1];
So your matches do not contain a [1] element, so you do not 'hit' anything there.
Debugging howto:
- remove everything after
$head=$matches[1];
- Is the problem still there: you've found your line. Is it not? It's the second line.
- For the
preg_match
that is the problem, echo the$html
(or$head
) vars to see their contents. Mind you, the will not show up in a browser if they are html, so check the source or do this on the commandline. - Try to figure out if your var has the content you expect, and if you could actually match with your regular expression. If not: fix the expression or the var. if so:
- Make a test-file with the contents of the var hardcoded in your preg_match. Is the problem still there? maybe
var_dump
your$matches
to be sure - If problem still there (you've probably hit the problem by now, but nevertheless): post the test code (that last testfile with the hardcoded preg_match that troublesome) and ask where you are getting it wrong.
bottomline: post a MINIMAL piece of code where it still goes wrong. You're bound to find the problem on the way of making that minimal problem, but if you do not it's a lot easier for us to help you.
Nowhere in your code are you actually checking that you managed to successfully open the document to parse, also can you show us more of the code nor do you even check to see if $matches
has any content. First thing I suggest you do is to format your code so it is easier to read then look at some if statements to make sure that things are being set.
Just the second tip alone will save you countless hours in the future.
Also remember, arrays start at [0]
so if you know that matches is only going to have one thing stored in it, try changing the $matches[1]
to $matches[0]
I'm going to go ahead and say that your issue is that you don't have good error messages, not that you've an undefined index.
Follow the track to get to that point:
$head=$matches[1];
is an undefined index.$matches
is retrieved by looking for thehead
of some HTML which is being parsed with a regexp (*HUGE* No-no by the way. You should really look into a legit HTML parser)- That happens because there is a problem with whatever calls
_parseHtml
. _parseHtml
is called bycreateDoc
.- You're passing in
"<h1>Testing data </h1>"
as HTML.
All of that given, OF COURSE you are getting no index found, you're not passing in valid HTML, so it is unable to convert it. Try "<html><head></head><body><h1>Testing data </h1></body></html>"
(note: your class does not accept <head />
as a valid head tag... that's a problem).
And there are other areas where this class can be improved.
- You're using PHP4 style OOP. Unless PHP4 is part of the functional spec. this is a big no-no. You want _parseHtml to be private...
- At one point I noticed this:
EOH;
return $return;`
The probem is that Heredoc does not allow for indented closings. It's in big, red letters. I think they mean it. createDocFromURL
does not allow for https$doc.=$this->htmlBody;
(increateDoc
) is not consistent with the code immediately preceding and following it -- everything works withget<value>
and that line is a direct access of a property.- You have a fotter in your class (a typo in
getFotter
) - If PHP 5 is an option, you should use
file_put_contents
inwrite_file
. - You have inconsistent naming of methods --
write_file
v.s.getHeader
I'm not trying to knock you down, but most of these have a large potential for causing problems in the future. You really should consider them.
精彩评论