整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Python實現XML快速轉換json

          Python實現XML快速轉換json

          景:

          以前的項目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

          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

          你可能知道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

          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; }
          

          簡單技巧:

          1. 打印第一個salary標簽:
          $ xmllint --xpath 'string(//salary)' foo.xml
          70000
          
          1. 打印所有的salary標簽(請注意,以這種形式打印并不特別有用):
          $ xmllint --xpath '//salary/text()' foo.xml
          7000090000
          
          1. 計算person標簽的數量:
          $ xmllint --xpath 'count(//person)' foo.xml
          2
          
          1. 分別打印每個人的salary:
          $ xmllint --xpath '//person[1]/salary/text()' foo.xml
          70000
          $ xmllint --xpath '//person[2]/salary/text()' foo.xml
          90000
          
          1. 打印bob的salary:
          $ xmllint --xpath '//person[@name="bob"]/salary/text()' foo.xml 
          70000
          
          1. 打印第二個人的name:
          $ xmllint --xpath 'string(//person[2]/@name)' foo.xml
          sue
          

          Namespaces

          上述示例顯示,當你擁有一個不錯的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 --shell

          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對于這個任務來說稍微容易一些

          $ 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

          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

          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 腳本編程最佳實踐》專欄,里面有我在一線互聯網大廠的實際生產經驗和最佳實踐,幫助你高效完成各種自動化任務。


          主站蜘蛛池模板: 国精产品一区二区三区糖心| 国产成人AV区一区二区三| 亚洲欧美日韩一区二区三区在线 | 国产精品一区二区三区高清在线| 人妻在线无码一区二区三区| 久久青青草原一区二区| 国产主播在线一区| 国产另类ts人妖一区二区三区 | 国精产品一区一区三区有限在线| 日本一区二区三区在线看| 亚洲AV美女一区二区三区| 亚洲av无码成人影院一区| 国产高清在线精品一区二区| 精品国产a∨无码一区二区三区| 日韩免费视频一区| 欧美成人aaa片一区国产精品| 精品福利一区二区三区| 无码视频免费一区二三区| 奇米精品一区二区三区在线观看| 立川理惠在线播放一区| 老熟妇高潮一区二区三区| 国产日本亚洲一区二区三区| 无码人妻精品一区二区三区夜夜嗨 | 日本一区二区三区日本免费| 色一乱一伦一图一区二区精品| 色一情一乱一伦一区二区三区日本| 熟妇人妻一区二区三区四区| 午夜精品一区二区三区在线观看| 麻豆AV无码精品一区二区 | av无码一区二区三区| 精品不卡一区中文字幕| 国产精品一区二区三区免费| 国产一区玩具在线观看| 国产亚洲福利精品一区| 精品亚洲A∨无码一区二区三区 | 国产日韩精品视频一区二区三区| 午夜福利国产一区二区| 无码精品视频一区二区三区| 久久久久人妻一区二区三区| 国产情侣一区二区| 精品日本一区二区三区在线观看 |