Re: HTML parsing module handles known and unknown encoding
by Corion (Patriarch) on Nov 16, 2011 at 15:49 UTC
|
It seems that XML::LibXML has thought about the problem and solved in the way that you should always pass octets to XML::LibXML. If you have an encoding handy, you're allowed to tell XML::LibXML about it, but it's not necessary.
I'm not sure how well XML::LibXML works with UTF-16LE and/or UTF-16BE and BOMs - you might need to use some regular (byte-)expressions to handle the BOM yourself.
| [reply] |
|
That works fine for XML since XML must specify its encoding within the document (binary format), but not so much with HTML where the encoding is specified outside of the document (text format).
I don't see any way of specifying the encoding of an HTML document, which is weird because XML::LibXML supposedly handles HTML.
XML::LibXML handles UTF-16 just fine.
| [reply] |
|
| [reply] [d/l] |
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8"
+ />
Of course this will really only work in cases where the encoding is some superset of ASCII (like iso8859-*, utf8 etc). | [reply] [d/l] [select] |
|
|
|
I thought that you could set the encoding through XML::IbXML::Document->setEncoding, but for that to work, you need to parse it first, which likely will ruin the encoded characters.
| [reply] |
Re: HTML parsing module handles known and unknown encoding
by ikegami (Patriarch) on Nov 16, 2011 at 19:08 UTC
|
XML parsers should expect encoded documents since the encoding is specified in the document itself. This is what XML::LibXML expects. (Even when using the HTML parsing methods, which is problematic.)
HTML parsers should expect decoded documents since the encoding is not specified in the document itself. You are clearly dealing with HTML since you mention "HTTP header".
And that's where you should be looking, in the tool that handles the HTTP transfer. $response->decoded_content() will decode the HTML for you, based on the HTTP header, BOM and META elements (if HTML).
The default charset decoded_content uses is is iso-8859-1, but you can can change it to cp1252 by passing default_charset => 'cp1252' as arguments to decoded_content.
my $decoded_html = $response->decoded_content(default_charset => 'cp12
+52');
| [reply] [d/l] [select] |
|
HTML parsers should expect decoded documents since the encoding is not specified in the document itself.
Indeed, if you know the encoding of the document, from the HTTP header or somewhere else, then you should decode the HTML using that, so the HTML parser should accept such a decoded string. However, in the real world, you'll often find that HTML documents are served over HTTP where the HTTP headers don't tell the encoding of the document. In that case, you'll need a way to find the encoding from the document itself. A HTML parser should support both of these cases.
Update: ikegami warns me that he writes in the post that LWP can find the encoding from the meta tag. I'll definitely look at this, for even if I don't use LWP to retrieve the document through HTTP, I can probably ask it to find the meta tag (LWP interface is usually quite nice in such things) or at the very least I can look at the implementation. Thank you for the hint.
| [reply] |
|
However, in the real world, you'll often find that HTML documents are served over HTTP where the HTTP headers don't tell the encoding of the document.
You appear to have missed crucial information in my post. Like I said, $response->decoded_content() will decode the HTML for you, based on the HTTP header, BOM and META elements (if HTML).
In that case, you'll need a way to find the encoding from the document itself. A HTML parser should support both of these cases.
Sure, though I'm not familiar with an HTML parser that supports both.
| [reply] [d/l] |
Re: HTML parsing module handles known and unknown encoding
by kennethk (Abbot) on Nov 16, 2011 at 17:45 UTC
|
Forgive my ignorance, but how does that following not meet your spec? Obviously I haven't included long characters in the test, but I would like to understand what the trip-ups are for my own education.
#!/usr/bin/perl -w
use strict;
require HTML::TreeBuilder;
my $tree = HTML::TreeBuilder->new; # empty tree
$tree->parse($_) while <DATA>;
$tree->eof;
$tree->elementify();
# Looking for
# <meta http-equiv=Content-Type content="text/html; charset=windows-12
+52">
my $content_type = $tree->look_down(
'_tag', 'meta',
sub {
my $elem = shift;
$elem->attr('http-equiv') eq 'Content-Type';
}
);
print $content_type->attr('content'), "\n";
__DATA__
<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:m="http://schemas.microsoft.com/office/2004/12/omml"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=windows-1252
+">
<meta name=ProgId content=Word.Document>
<meta name=Generator content="Microsoft Word 14">
<meta name=Originator content="Microsoft Word 14">
<link rel=File-List href="junk_files/filelist.xml">
<link rel=themeData href="junk_files/themedata.thmx">
<link rel=colorSchemeMapping href="junk_files/colorschememapping.xml">
</head>
<body lang=EN-US style='tab-interval:.5in'>
<div class=WordSection1>
<p class=MsoNormal>This is some text</p>
</div>
</body>
</html>
| [reply] [d/l] |
|
| [reply] [d/l] [select] |