以前的项目web的数据采用xml方式,现在更多采用JSON方式,那两者有什么差别,为什么技术面上更多的倾向用JSON呢?
我们先看看,JSON 与 XML 的不同之处:
1.JSON 不需要结束标签
2.JSON 更加简短
3.JSON 读写速度更快
4.JSON 可以使用数组
5.XML 需要使用 XML 解析器来解析,JSON 可以使用标准的 JavaScript 函数来解析
JSON.parse(): 将一个 JSON 字符串转换为 JavaScript 对象。
JSON.stringify(): 于将 JavaScript 值转换为 JSON 字符串。
那为什么 JSON 比 XML 更好呢?绝对不是无的放矢的:
1.XML 比 JSON 更难解析。
2.JSON 可以直接使用现有的 JavaScript 对象解析。
3.针对 AJAX 应用,JSON 比 XML 数据加载更快,而且更简单
# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import json
import sys
import time
def trans_xml_to_json(xml_path,outurl):
start=(time.time())
#获取xml文件
xml_file=open(xml_path, 'r', encoding='utf-8')
#读取xml文件内容
xml_str=xml_file.read()
#将读取的xml内容转为json
dic=xmltodict.parse(xml_str)
end=(time.time())
print('xml read use:{}'.format((end- start)*1000))
with open(outurl, 'w') as f:
# json.dump(file, f)
json.dump(dic, f, indent=4, ensure_ascii=False)
f.close()
if __name__=='__main__':
trans_xml_to_json('N2V.xml', 'N2VTemp.json')
start=(time.time())
with open('N2VTemp.json', 'r', encoding='gbk') as f:
redajson=json.load(f)
print('json -Use:{}'.format((time.time() - start) * 1000))
print(redajson)
f.close()
加入一个xml文件,示范的是一个160kb大小的文件
执行结果对比
发现XML的读取耗时是json的6倍,效率确实要低很多。
通过这个比对,在网络使用时还是快才是王道,那就选择json来作为数据处理的源头。
本期分享就到这了,谢谢大家。
tml2pdf
PDFBox是一个Java库,可用于创建,修改和提取PDF文件的内容。它是一个Apache软件基金会的项目,使用Apache License 2.0许可证。
PDFBox提供了一组API,可用于提取文本和图像,添加和删除页面,提取PDF元数据和加密PDF文件等。
<!-- 将 html 转换为 xml 工具库 -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.1</version>
</dependency>
<!-- 第三方 pdfbox 包装库,提供 html 转 pdf 功能 -->
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>1.0.10</version>
</dependency>
// 获取 java 版本
String version=System.getProperty("java.specification.version");
// 获取系统类型
String platform=System.getProperty("os.name", "");
platform=platform.toLowerCase().contains("window") ? "win" : "linux";
// 当前程序目录
String current=System.getProperty("user.dir");
System.out.println(String.format("current=%s", current));
// html 文件路径
File index=Paths.get(current, "..", "index.html").toFile();
if (!index.exists()) {
System.out.println(String.format("file not exist,file=%s", index.getAbsolutePath()));
return;
}
try {
Document doc=Jsoup.parse(index, "UTF-8");
// 补全标记
doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
File file=Paths.get(current, String.format("java%s_%s.pdf", version, platform)).toFile();
FileOutputStream stream=new FileOutputStream(file);
PdfRendererBuilder builder=new PdfRendererBuilder();
// NOTE 字体问题,文档中出现过的字段,需要手动加载字体
builder.useFont(Paths.get(current, "..", "fonts", "simsun.ttc").toFile(), "SimSun");
builder.useFont(Paths.get(current, "..", "fonts", "msyh.ttc").toFile(), "font-test");
builder.useFont(Paths.get(current, "..", "fonts", "msyh.ttc").toFile(), "Microsoft YaHei UI");
// NOTE 设置根目录
String baseUrl=Paths.get(current, "..").toUri().toString();
builder.withHtmlContent(doc.html(), baseUrl);
builder.toStream(stream);
builder.run();
} catch (IOException e) {
throw new RuntimeException(e);
}
pdfbox-demo/java1.8_win.pdf · yjihrp/linux-html2pdf-demo - Gitee.com
pdfbox-demo/java11_linux.pdf · yjihrp/linux-html2pdf-demo - Gitee.com
# 查看 pdf 内部结构
java -jar pdfbox-app debug path-to-pdf/test.pdf
java -jar debugger-app path-to-pdf/test.pdf
测试结果
下一篇 5-LINUX HTML 转 PDF-selenium
要使用sed、awk、grep等工具进行尝试(这会导致不可预期的结果)。在许多情况下,你最好选择使用支持XML数据的编程语言进行处理。如果必须使用shell脚本,有一些专门用于解析HTML和XML文件的工具可供使用。
你可能知道Lynx是一个带有极限限制的终端模式Web浏览器。确实如此,但它也是一个可编程的HTML解析器。它特别擅长从文档中提取链接并将其打印出来:
如果你想要包括图像链接,请添加-image_links选项。现在,根据你的需求过滤链接应该相对简单,因为每个链接都在单独的一行上,没有HTML标签的干扰。
$ lynx -dump -listonly -nonumbers http://mywiki.wooledge.org/
http://mywiki.wooledge.org/EnglishFrontPage?action=rss_rc&unique=1&ddiffs=1
http://mywiki.wooledge.org/EnglishFrontPage?action=edit
http://mywiki.wooledge.org/EnglishFrontPage
http://mywiki.wooledge.org/EnglishFrontPage?action=raw
http://mywiki.wooledge.org/EnglishFrontPage?action=print
http://mywiki.wooledge.org/EnglishFrontPage?action=AttachFile&do=view&target=Greg's-wiki.zip
[...]
你可能会认为wget在这方面也很好用,对吧?我的意思是,它有递归镜像模式,所以显然内部做了这种操作。祝你好运,试图找到一种方法让wget将URL打印出来而不是下载全部文件。
我试着尝试了一下,找到了一种方法。没有经过充分测试。我们可以使用--rejected-log和始终匹配的--reject-regex参数。我们使用--spider选项以不保存文件的方式执行。
$ wget -q --spider -r --rejected-log=rejected --reject-regex=^ http://mywiki.wooledge.org/
$ cat rejected
REASON U_URL U_SCHEME U_HOST U_PORT U_PATH U_PARAMS U_QUERY U_FRAGMENT P_URL P_SCHEME P_HOST P_PORT P_PATH P_PARAMS P_QUERY P_FRAGMENT
REGEX http%3A//mywiki.wooledge.org/moin_static198/common/js/common.js SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/common/js/common.js http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/common.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/common.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/screen.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/screen.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/print.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/print.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
REGEX http%3A//mywiki.wooledge.org/moin_static198/modernized/css/projection.css SCHEME_HTTP mywiki.wooledge.org 80 moin_static198/modernized/css/projection.css http%3A//mywiki.wooledge.org/ SCHEME_HTTP mywiki.wooledge.org 80
[...]
要将链接提取到标准输出中:
$ wget -q --spider -r --rejected-log=/dev/stdout --reject-regex=^ http://mywiki.wooledge.org/ | tail -n +2 | cut -f 2
http%3A//mywiki.wooledge.org/moin_static198/common/js/common.js
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/common.css
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/screen.css
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/print.css
http%3A//mywiki.wooledge.org/moin_static198/modernized/css/projection.css
[...]
xmllint是处理大多数XML的最佳选择。不幸的是,使用它需要学习XPath,而我并不知道任何合理的XPath入门教程。以下是一些简单的技巧。它们是使用以下输入文件演示的:
<staff>
<person name="bob"><salary>70000</salary></person>
<person name="sue"><salary>90000</salary></person>
</staff>
请注意,xmllint在输出中不添加换行符。如果你用CommandSubstitution进行捕获,这不是问题。但如果你在交互式shell中测试,这将很快变得很烦人。你可以考虑编写一个包装函数,例如:
xmllint() { command xmllint "$@"; echo; }
简单技巧:
$ xmllint --xpath 'string(//salary)' foo.xml
70000
$ xmllint --xpath '//salary/text()' foo.xml
7000090000
$ xmllint --xpath 'count(//person)' foo.xml
2
$ xmllint --xpath '//person[1]/salary/text()' foo.xml
70000
$ xmllint --xpath '//person[2]/salary/text()' foo.xml
90000
$ xmllint --xpath '//person[@name="bob"]/salary/text()' foo.xml
70000
$ xmllint --xpath 'string(//person[2]/@name)' foo.xml
sue
上述示例显示,当你拥有一个不错的XML解析器时,解析XML是相当容易的,但这违背了XML的目的,即让每个人都感到痛苦。因此,一些聪明人引入了XML命名空间。
一个典型的maven构建文件(称为pom.xml)就是这样的例子,大致如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-project</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
通常还会有几百行用于依赖项,但我们来保持简洁。
根据前一章的示例,我们知道从该文件中提取版本只需使用xpath /project/version/text():
$ xmllint --xpath '/project/version/text()' pom.xml
XPath set is empty
嗯,不是这样的,因为作者聪明地为这个xmlns="http://maven.apache.org/POM/4.0.0"添加了一个默认命名空间,所以现在你首先必须指定确切的URL,然后才能指明要获取的版本元素内部的文本。
xmllint的--xpath选项没有办法指定命名空间,所以它现在无法使用(除非你编辑文件并删除命名空间声明)。但其shell功能确实允许设置命名空间。
xmllint --shell pom.xml << EOF
setns ns=http://maven.apache.org/POM/4.0.0
cat /ns:project/ns:version/text()
EOF
/ > / > -------
1.0-SNAPSHOT
/ >
耶!我们得到了版本号...外加一些来自xmllint shell的提示和废话,之后必须将其删除。
xmlstarlet对于这个任务来说稍微容易一些
$ xmlstarlet sel -N ns=http://maven.apache.org/POM/4.0.0 -t -v /ns:project/ns:version -n pom.xml
1.0-SNAPSHOT
Python也附带了一个XML解析器,通常比xmllint和xmlstarlet更常用。它也可以以一种笨拙的方式处理命名空间。
$ python -c 'import xml.etree.ElementTree as ET;print(ET.parse("pom.xml").find("{http://maven.apache.org/POM/4.0.0}version").text)'
1.0-SNAPSHOT
xsltproc恰好在大多数Linux系统上安装。例如提取播客的标题和URL:
xslt() {
cat << 'EOX'
<?xml version="1.0"?>
<x:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
<x:output method="text" />
<x:template match="/">
<x:for-each select="//item">
<x:text># </x:text>
<x:value-of select="./title/text()" /><x:text>
<!-- newline --></x:text>
<x:value-of select="enclosure/@url" /><x:text>
</x:text>
</x:for-each>
</x:template>
</x:stylesheet>
EOX
}
curl -s http://podcasts.files.bbci.co.uk/p02nq0lx.rss | xsltproc <(xslt) -
如果你想学习如何编写更加健壮和可靠的 Shell 脚本,减少生产环境中的错误和故障,那么关注我吧!我会分享 Shell 编程的最佳实践和建议,帮助你提高 Shell 脚本的鲁棒性和可维护性。如果你想深入了解 Shell 编程的实际应用和技巧,可以关注我的《Shell 脚本编程最佳实践》专栏,里面有我在一线互联网大厂的实际生产经验和最佳实践,帮助你高效完成各种自动化任务。
*请认真填写需求信息,我们会在24小时内与您取得联系。