<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>caicono的自由世界 &#187; xml</title>
	<atom:link href="http://www.caicono.info/blog/wordpress/tag/xml/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.caicono.info/blog/wordpress</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 09 May 2010 07:25:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>思考充分再行动 &#8211; python试水记</title>
		<link>http://www.caicono.info/blog/wordpress/2010/01/a-beginner-diving-into-python/</link>
		<comments>http://www.caicono.info/blog/wordpress/2010/01/a-beginner-diving-into-python/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 10:31:53 +0000</pubDate>
		<dc:creator>caicono</dc:creator>
				<category><![CDATA[相关技术]]></category>
		<category><![CDATA[bookmark]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.caicono.cn/articles/%e6%80%9d%e8%80%83%e5%85%85%e5%88%86%e5%86%8d%e8%a1%8c%e5%8a%a8-python%e8%af%95%e6%b0%b4%e8%ae%b0.html</guid>
		<description><![CDATA[这两天突发奇想觉得python脚本语言很简单，很实用，就一头扎入其中玩了几天，全然不顾还有一堆的工作等待我去crack。想起某人的话：“职业人与学生最大的差别在于兴趣的时候，是服从任务调遣还是内心。职业人只要有任务在身，deadline一旦设定就要努力向前，争取如期完成任务。而学生喜欢懒懒散散，尤其以兴趣来了为借口，东一榔头，西一榔头的瞎忙活，结果工期总是一推再推，比预计要花出多几倍的时间”。我目前就缺乏这种职业精神，原来做好的计划在变化和所谓兴趣面前烟消云散了。
在这里记录一下关于python试水的心得和过程。一方面是python试水手记，另一方面由于自己失误，犯了个大错误，因此这篇blog这也是对自己的一个提醒：因为在开始一个程序调试之前，很重要的一个因素：外部接口的支持程度，没有考虑到，导致瞎忙活了一天多时间，最后还没完成原始目标。
这两天在浏览时发现一个问题，有些pdf电子书没有做bookmark，不容易定位章节。网上有一个成熟的软件PdfBookmark可以根据一个xml文件生成pdf的书签。我就萌生用python写个脚本生成相应xml从而生成自己想要的书签的想法。
以后浏览书籍的过程是这样：
1. 浏览pdf书籍，手动记录章节和页码信息在一个excel或者txt文件中。
2. 用python读取这个简单的txt文件并按照规则生成PdfBookmark所需xml
3.用此xml更新pdf文件的bookmark
很简单的任务和目标，可惜自己之前没有调研软件PdfBookmark是否支持中文书签，实验了它的英文example，觉得很不错，就赶紧动手了。下面是整个实验试水的一个记录。
 
Setuptools 和 easyInstall的关系？
CPAN PyPI distutils eggs package management
setuptools是对python的package Index进行管理的工具，python工具包的后缀名都是.egg,需要专门的工具进行安装：easyInstall。
.egg 是windows平台上的二进制文件，可以直接被程序easyInstall调用。
目前的setuptools只能支持到python 2.6版本，而python3.1的setuptools没有官方版本。有网友开发出了可兼容python3的setuptools. http://regebro.wordpress.com/2009/02/01/setuptools-and-easy_install-for-python-3/
文章同时指出，当前支持3.1的python库还不多。不过距离当时发表时间已经过去1年了，不知目前的python 3.1的package库支持能力如何，应该有极大的提高和长进。就在1月4号，pyhon官方发布了最新的一批文档，更新频率还是挺快的。
 
lxm包的安装
1. 去http://codespeak.net/lxml/ ，下载lxml包。最新版本2.2.4，09年11月11日发布。
2. 然后根据instruction进行安装：http://codespeak.net/lxml/installation.html
3. 在此之前有两个依赖包。先不管。
4. 获取工具(也是基于python的一个功能模块)easy_install（Easy Install is a python module (easy_install) bundled with setuptools that lets you automatically download, build, install, and manage Python packages.）windows平台上，Pyhon 2.6版本会之间附带上easy_install.exe，但在3.1版本安装目录下，没有这个安装文件。而且，pyhon3.1没有easy_install工具。那么3.1如何安装更新包呢？ 不解。
找到一封邮件回复说明python3.1暂不支持lxml，我就不想再花费时间去找新的工具解决这个big problem了。
Dov Reshef wrote:
&#62; I&#8217;m trying to install lxml 2.2.2 for python 3.1. (I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>这两天突发奇想觉得python脚本语言很简单，很实用，就一头扎入其中玩了几天，全然不顾还有一堆的工作等待我去crack。想起某人的话：“职业人与学生最大的差别在于兴趣的时候，是服从任务调遣还是内心。职业人只要有任务在身，deadline一旦设定就要努力向前，争取如期完成任务。而学生喜欢懒懒散散，尤其以兴趣来了为借口，东一榔头，西一榔头的瞎忙活，结果工期总是一推再推，比预计要花出多几倍的时间”。我目前就缺乏这种职业精神，原来做好的计划在变化和所谓兴趣面前烟消云散了。</p>
<p>在这里记录一下关于python试水的心得和过程。一方面是python试水手记，另一方面由于自己失误，犯了个大错误，因此这篇blog这也是对自己的一个提醒：因为在开始一个程序调试之前，很重要的一个因素：外部接口的支持程度，没有考虑到，导致瞎忙活了一天多时间，最后还没完成原始目标。</p>
<p>这两天在浏览时发现一个问题，有些pdf电子书没有做bookmark，不容易定位章节。网上有一个成熟的<a href="http://www.traction-software.co.uk/servertools/pdfbookmark/" target="_blank">软件PdfBookmark</a>可以根据一个xml文件生成pdf的书签。我就萌生用python写个脚本生成相应xml从而生成自己想要的书签的想法。</p>
<p>以后浏览书籍的过程是这样：</p>
<p>1. 浏览pdf书籍，手动记录章节和页码信息在一个excel或者txt文件中。</p>
<p>2. 用python读取这个简单的txt文件并按照规则生成PdfBookmark所需xml</p>
<p>3.用此xml更新pdf文件的bookmark</p>
<p>很简单的任务和目标，可惜自己之前没有调研<a href="http://www.traction-software.co.uk/servertools/pdfbookmark/" target="_blank">软件PdfBookmark</a>是否支持中文书签，实验了它的英文example，觉得很不错，就赶紧动手了。下面是整个实验试水的一个记录。</p>
<p> </p>
<h2>Setuptools 和 easyInstall的关系？</h2>
<p>CPAN PyPI distutils eggs package management</p>
<p>setuptools是对python的package Index进行管理的工具，python工具包的后缀名都是.egg,需要专门的工具进行安装：easyInstall。</p>
<p>.egg 是windows平台上的二进制文件，可以直接被程序easyInstall调用。</p>
<p>目前的setuptools只能支持到python 2.6版本，而python3.1的setuptools没有官方版本。有网友开发出了可兼容python3的setuptools. <a href="http://regebro.wordpress.com/2009/02/01/setuptools-and-easy_install-for-python-3/">http://regebro.wordpress.com/2009/02/01/setuptools-and-easy_install-for-python-3/</a></p>
<p>文章同时指出，当前支持3.1的python库还不多。不过距离当时发表时间已经过去1年了，不知目前的python 3.1的package库支持能力如何，应该有极大的提高和长进。就在1月4号，pyhon官方发布了最新的一批文档，更新频率还是挺快的。</p>
<p> </p>
<h2>lxm包的安装</h2>
<p>1. 去<a href="http://codespeak.net/lxml/">http://codespeak.net/lxml/</a> ，下载lxml包。最新版本2.2.4，09年11月11日发布。</p>
<p>2. 然后根据instruction进行安装：<a href="http://codespeak.net/lxml/installation.html">http://codespeak.net/lxml/installation.html</a></p>
<p>3. 在此之前有两个依赖包。先不管。</p>
<p>4. 获取工具(也是基于python的一个功能模块)easy_install（Easy Install is a <strong>python module</strong> (easy_install) bundled with setuptools that lets you automatically download, build, install, and manage Python packages.）windows平台上，Pyhon 2.6版本会之间附带上easy_install.exe，但在3.1版本安装目录下，没有这个安装文件。而且，pyhon3.1没有easy_install工具。那么3.1如何安装更新包呢？ 不解。</p>
<p>找到一封邮件回复说明python3.1暂不支持lxml，我就不想再花费时间去找新的工具解决这个big problem了。</p>
<p>Dov Reshef wrote:</p>
<p>&gt; I&#8217;m trying to install lxml 2.2.2 for python 3.1. (I&#8217;m using the egg for</p>
<p>&gt; python version 3, simply unpacking it to the site-packages folder). However,</p>
<p>&gt; when I try to use it in my code I get &#8220;ImportError: DLL load failed&#8221;, which</p>
<p>&gt; if I understand it correctly, means that it can&#8217;t find the etree.dll even</p>
<p>&gt; though it&#8217;s right there in my site-packages folder (etree.pyd).</p>
<p>3.1 isn&#8217;t 3.0 compatible, I guess.</p>
<p>We don&#8217;t currently have binary eggs for 3.1, sorry.</p>
<p>5. 只能换到2.6平台，重新将上面的工作继续一遍.</p>
<p>C:\Documents and Settings\Administrator&gt;easy_install</p>
<p>Easy_install 总是不能在其它目录下运行，明明将D:\Python26\Scripts;加入了path路径。后来发现D:\Python26\Scripts;必须在D:\Python26这个路径之后，系统才能将其识别。（这也是一个诡异的现象）</p>
<p>下载lxml-2.2.4-py2.4-win32.egg，然后运行安装程序：</p>
<p>C:\Documents and Settings\Administrator&gt;easy_install C:\lxml-2.2.4-py2.4-win32.egg</p>
<p>终于将lxml装入python2.6的库中。</p>
<p>在文件夹：D:\Python26\Lib\site-packages 可以看到新增了lxml-2.2.4-py2.4-win32.egg文件夹以及一些新的文件。</p>
<p>在python 2.6运行cmd中，终于可以import lxml了</p>
<p>Python3中依然不能导入lxml，因为目前无法安装。</p>
<h2>中文在读写xml文档中的问题</h2>
<p>因为在写入中文时出现错误：</p>
<p>name = etree.SubElement(bookmark,&#8217;Name&#8217;)</p>
<p>name.text = &#8220;&#8221;+item[0]</p>
<p>ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes</p>
<p>读取中文txt文件需要指定编码方式，否则open函数不知如何对字节进行解码为相应的字符。</p>
<p>发现windows平台上python默认的编码格式为：cp936，使用下面这个方法得到：</p>
<p>print(locale.getpreferredencoding())</p>
<p>在我的IDLE编辑器中，第一行有一句注释：# -*- coding: cp936 -*-</p>
<p>这个好像就是将.py文本的编码格式设定为cp936。让解释器对.py文件解释时识别其中的非ascii字符。我将其改成utf-8, getpreferredencoding输出的依然是cp936。</p>
<p>因为python2.6不支持open(‘’,encoding=’utf-8’)的语法，只好采用codecs包的open方法，但是用utf-8编码方式入读中文文件依然出现error。</p>
<p>import codecs</p>
<p>book_file = codecs.open(&#8216;bookmark-logic.txt&#8217;,'r&#8217;)</p>
<p>File &#8220;D:\Python26\lib\encodings\utf_8.py&#8221;, line 16, in decode</p>
<p>return codecs.utf_8_decode(input, errors, True)</p>
<p>UnicodeDecodeError: &#8216;utf8&#8242; codec can&#8217;t decode bytes in position 0-1: invalid data</p>
<p>此时很明显是因为输入文件就不是用utf-8方式编码的。解决方法，用记事本将输入文件改成utf-8编码保存后即可。</p>
<p>但是又出现新问题，生成的文档无法正常显示中文。这是为何？？当时以为问题肯定出在这一句：</p>
<p><span id="Code_Closed_Text_161565" class="cnblogs_code_Collapse">中文显示有问题的xml片段</span></p>
<div class="cnblogs_code">
<div class="cnblogs_code">
<pre><img id="Code_Closed_Image_204402" onclick="function onclick()
{
this.style.display='none'; document.getElementById('Code_Closed_Text_204402').style.display='none'; document.getElementById('Code_Open_Image_204402').style.display='inline'; document.getElementById('Code_Open_Text_204402').style.display='inline';
}" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" alt="" width="11" height="16" align="top" /><img id="Code_Open_Image_204402" style="display: none" onclick="function onclick()
{
this.style.display='none'; document.getElementById('Code_Open_Text_204402').style.display='none'; getElementById('Code_Closed_Image_204402').style.display='inline'; getElementById('Code_Closed_Text_204402').style.display='inline';
}" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" alt="" width="11" height="16" align="top" /><span id="Code_Open_Text_204402" style="display: none"><span style="color: #0000ff">&lt;?</span>xml version="1.0" encoding="utf-8" <span style="color: #0000ff">?&gt;</span>
<span style="color: #0000ff">&lt;</span><span style="color: #800000">Bookmarks</span><span style="color: #0000ff">&gt;</span>
  <span style="color: #0000ff">&lt;</span><span style="color: #800000">Bookmark</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">Name</span><span style="color: #0000ff">&gt;</span>&amp;#65279;&amp;#20013;&amp;#25991;<span style="color: #0000ff">&lt;/</span><span style="color: #800000">Name</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">page</span><span style="color: #0000ff">&gt;</span>46<span style="color: #0000ff">&lt;/</span><span style="color: #800000">page</span><span style="color: #0000ff">&gt;</span>
    <span style="color: #0000ff">&lt;</span><span style="color: #800000">level</span><span style="color: #0000ff">&gt;</span>1&amp;#13;
<span style="color: #0000ff">&lt;/</span><span style="color: #800000">level</span><span style="color: #0000ff">&gt;</span>
</span><span id="Code_Open_Text_161565" style="display: none">
 
</span>
name.text = item[0]

item的编码方式是utf-8，直接赋值给text，text可能会是unicode或者原始字符类型str,不一样。为何显示出来的unicode会是这种&amp;#65279;编码形式呢？

text type is: &lt;type 'unicode'&gt;

text type is: &lt;type 'str'&gt;

item type is: &lt;type 'unicode'&gt;

经过找寻，发现不是name.text = item[0]的问题，而是在etree.tostring(root, encoding='utf-8', pretty_print=True) 少了对encoding的设置。设置后即可。

对item中的中文进行utf-8编码或者utf-8的解码均有问题，因为item[0]本身是unicode对象，不能再进行encode，但第二种情况，decode为何出现ordinal not in range(128) 的error？？
<div class="cnblogs_code">
<pre><img id="Code_Closed_Image_244203" onclick="function onclick()
{
this.style.display='none'; document.getElementById('Code_Closed_Text_244203').style.display='none'; document.getElementById('Code_Open_Image_244203').style.display='inline'; document.getElementById('Code_Open_Text_244203').style.display='inline';
}" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" alt="" width="11" height="16" align="top" /><img id="Code_Open_Image_244203" style="display: none" onclick="function onclick()
{
this.style.display='none'; document.getElementById('Code_Open_Text_244203').style.display='none'; getElementById('Code_Closed_Image_244203').style.display='inline'; getElementById('Code_Closed_Text_244203').style.display='inline';
}" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" alt="" width="11" height="16" align="top" /><span id="Code_Open_Text_244203" style="display: none">name.text = (""+item[0]).encode('utf-8')
ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes

name.text = (""+item[0]).decode('utf-8')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)</span>
<h2>Unicode编码与实际内容：</h2>

﻿中文 46 1

基本原理 48 2

2.huise didai 53 2

unicode编码之后的实际字符为：

[u'\ufeff\u4e2d\u6587\t46\t1\r', u'\u57fa\u672c\u539f\u7406\t48\t2\r', u'2.huise didai\t53\t2\r', u'']

在读入每一行字符后，用re.splite(‘\t’)函数得到具体内容，但是最后一个单词后面会跟一个看不见的\r\t, 而显示出来为&amp;#13;并且换行。我在如何读取时不读入这个符号这个问题上困扰了很久。最后发现可以之间将其去除..

&lt;level&gt;2&amp;#13;

&lt;/level&gt;

后来发现直接调用string的方法：(string.strip())即可去除这个换行符。
<h3>题外话，</h3>

在这一次python3转2.6的过程中，发现语法差异还是不小：

比如2中不支持： #print('list display：{} {};'.format(count,item))

在3之前的版本，print都不是一个函数。
<h2>总结</h2>

到此为止，这个脚本基本能够搞定最初提出的生成相应xml的任务。可惜后来发现PdfBookmark无法识别unicode，还给他们公司发信询问了相关情况，确实目前版本不支持unicode，中文书签没法应用。这一次的任务无果而终，唯一收获是熟悉了python的相关细节如文件操作，xml解析等，并得到一个教训：<strong>做任务前要三思，考虑全面后方可行动！</strong></pre>
</div>
<p> </pre>
</div>
<div></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.caicono.info/blog/wordpress/2010/01/a-beginner-diving-into-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
