我最近买了一个Nook Simple Touch。我使用Calibre来管理我的电子书,并将它们转移到Nook。
由于B& N部分的epub规范的非标准实现,Nook ST在从多个来源引入时不显示封面图像。此处描述了此问题:http://john.nachtimwald.com/2011/08/21/nook-covers-not-showing-up/ 基本上Nook ST要求封面的XML属性采用以下格式:
<meta name="cover" content="id5" />
但是许多epub创作者都有这样的方式:
<meta content="id5" name="cover" />
然后Nook ST完全忽略了封面图片。
我手动编辑了epub文件中的content.opf文件。到目前为止,他们都有形象元,但它总是围绕“错误”的方式(错误,根据Nook)。
最近我一直在玩REGEX,主要是为了尝试自动清理由Calibre从PDF文件转换的epub。我仍然是REGEX的初学者。
我想知道的是我如何自动交换“名称”和“内容”属性?我认为它可以通过REGEX和脚本的组合来完成。我知道我在Python中使用的其他一些与epub相关的脚本。我在Mac(OS X)上,他们似乎运行良好。 AppleScript也可能是一个不错的选择,虽然我想要一些人可以在任何平台上运行的东西,因为我相信其他人会觉得这很有用。
以下是我预见的步骤:
〜解压缩epub文件
〜使用REGEX查找:
<meta content="???" name="cover">
〜如果找到,请使用REGEX将其更改为:
<meta name="cover" content="???">
〜使用正确的压缩过程将提取的文件拉回到epub中。
我在这里找到了信息:http://www.mobileread.com/forums/showthread.php?t=55681解释了如何正确压缩epub文件。基本上它需要这两个命令:
zip -X0 "full path to new epub file" mimetype
zip -rDX9 "full path to new epub file" * -x "*.DS_Store" -x mimetype
我想在线找到并使用的结果脚本(直到B&amp; N解决他们糟糕的epub / XML实现)。在Calibre论坛和mobileread论坛上发布它(因为它们是我熟悉的两个,并且已经看到人们讨论这个问题的手册修复)。
是否有人可以指导我如何创建这样的脚本?理想情况下,我真的很想知道如何创建脚本,所以随着时间的推移,我可以开始自己弄清楚这些事情(特别是REGEX部分,因为我看到它越来越有用)。
谢谢。
乔纳森
@Haldean:ADDED用于说明我对Haldean的评论意味着他的脚本是否以递归方式处理所有子文件夹中的所有content.opf文件。
> My_expanded_epubs
- -> epub_one_expanded
- - - -> content.opf
- -> epub_two_expanded
- - - -> content.opf
- -> epub_three_expanded
- - - -> content.opf
etc.
答案 0 :(得分:2)
如果您愿意使用shell脚本(我认为这是一个更好的选择),那么您可以使用sed one-liner:
sed 's/<meta content="\(.*\)" name="cover" \/>/<meta name="cover" content="\1" \/>/' [your-file]
这应该替换content
属性首先出现的所有元行,其中一行具有正确的顺序。一个等效的Python翻译是:
import re
import sys
with open(sys.argv[1]) as f:
for line in f:
# Match this line to the wrong-way-around meta tag, put the content in group 1
m = re.match(r'<meta content="(.*)" name="cover" />', line)
if not m:
print line
else:
print '<meta name="cover" content="%s" />' % m.group(1)
答案 1 :(得分:1)
我建议您使用sed来处理解压缩的文件,并执行以下操作:
sed -e 's/<[ ]*meta[ ]*content[ ]*=[ ]*"\(.*\)"[ ]*name[ ]*=[ ]*"cover"[ ]*\/*[ ]*>/<meta name="cover" content="\1" \/>/g'
请注意,此版本将处理额外或缺少的空格或斜杠。
您可能希望随后使用xml处理器(我建议使用lxml
创建一个python脚本)来验证您的编辑是否适用于任何创建的无效标记。
使用任何类型的XML工具来执行操作都极具吸引力,因为完全兼容的XML处理器可能会进行其他完全合法的更改,并且还会触发您的角落中的其他错误。使用sed
,您只能编辑所需文档的各个部分。
答案 2 :(得分:0)
我个人不会用正则表达式(its the wrong tool)来做这件事。你能用XSLT吗?
编辑:
这是一个演示。 http://www.xsltcake.com/slices/nvLRJ6
编辑:
如果你坚持用正则表达式做,你会想要一个这样的模式:
<meta content="([^"]+)" name="([^"]+)" \/>
我用disclaimer that this is the wrong tool说这个,并且有一些边缘情况会导致这种情况不可靠,我不推荐它。
答案 3 :(得分:-1)
我同意zapthedingbat's answer:这是一个XML问题,所以让我们使用专为XML设计的工具,即XSLT。
由于您是XSLT的新手,因此您需要一个XSLT处理器来尝试此解决方案。如果您使用的是* nix,xsltproc
是一个命令行处理器,默认情况下几乎肯定会安装,您可以使用此值来获得此解决方案。如果没有,您需要查看您选择的语言是否具有用于执行XSL转换的API。
以下是重新排序属性的一个非常简单的通用解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<!-- copy everything as is -->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="meta">
<!-- except for the <meta/> element, reverse the attribute order -->
<meta name="{@name}" content="{@content}"/>
</xsl:template>
</xsl:stylesheet>
以下是您的示例:
<root>
<meta content="id5" name="cover" />
</root>
使用xsltproc
:
$ xsltproc so.xsl so.xml
结果:
<root>
<meta name="cover" content="id5"/>
</root>