xml显示浏览器标签_浅析浏览器书签的导入和导出
瀏覽器有個實用的功能,但是可能用的頻率不高,就是書簽/收藏的導入和導出,因為現在一般瀏覽器都有云同步功能,所以這個功能存在感不強。
瀏覽器書簽是可以跨不同的瀏覽器導入的,所以意味著導出的文件肯定是有一個規范的,我簡單搜了一下沒有搜到,可能是各家約定俗成的規范,并沒有一個正式的標準。
通用的數據交換格式有很多,比如xml、json、yaml,json應該是使用最廣泛的,因為易于解析和存儲,尺寸也不大,所以很適合瀏覽器書簽的導出,但是,實際上現代瀏覽器導出的書簽文件是html文件。原因不詳,也沒有搜到相關信息,我猜測原因可能是html文件相對于json來說,普通用戶更為熟悉,其次,html文件可以直接使用瀏覽器打開,當然,json文件也可以使用瀏覽器打開,但是可能直接點擊的時候默認是用文本編輯器打開的,另外它們在瀏覽器的呈現方式也不一樣,html顯示的是一個普通的帶有一堆超鏈接的頁面,就是一個有點丑的網頁,而json打開有點類似源碼,不太友好,因為一般用戶導出書簽就是為了在另一個瀏覽器導入,所以屏蔽細節并沒有什么問題。
html和xml是類似的,所以解析和傳輸也很簡單,接下來看一下實例:
基本結構如上,每個文件夾下都有個書簽,導出的書簽源碼如下:
簡單分析一下:
1.標簽字母都是大寫
2.DOCTYPE聲明和普通HTML頁面不同
3.使用DL和DT來組織書簽,DL代表一個文件夾的內容列表,DT代表一個內容,可能是書簽也可能是文件夾,文件夾的話會有一個H3標簽來表示書簽的名字,書簽的話就是直接跟一個A標簽,DL標簽后都跟了一個小寫的p標簽,有部分標簽沒有閉合
4.H1標簽之前的都和書簽內容沒有什么關系
5.文件夾名稱H3標簽和超鏈接A標簽都有ADD_DATE和LAST_MODIFIED來保存時間信息,該屬性不存在也不影響
6.文件夾名稱H3標簽的屬性PERSONAL_TOOLBAR_FOLDER來表示該文件夾下的內容是否顯示到瀏覽器的工具欄,否則會默認放到瀏覽器的其他文件夾里,但也不一定,有的瀏覽器會有自己的行為
7.網頁的標題icon會轉換為base64格式放到ICON屬性上,這個屬性不存在也不影響
html其實就是普通字符串,所以可以手動生成,常見于一些導航網站和網址收藏工具的導出功能,如五花八門導航(http://lxqnsys.com/d),有一個需要注意的地方,就是html字符串必須格式化帶換行和縮進,下圖這種壓縮過的是不行的:
生成方式也很簡單,書簽是樹結構,所以遞歸循環拼接即可。
先看一下書簽數據的格式,忽略時間和icon:
let bookmarks = [ { name: '',// 文件夾或書簽名字 toolbar: true,// 是否顯示到工具欄 folder: true,// 是否是文件夾 children: [ { name: '', folder: true, children: [] }, { name: '',// 書簽名稱 url: ''// 書簽url } ] }]使用ES6的話可以直接使用模板字符串``來帶換行的拼接,很方便:
function createBookmarksStr (bookmarks) { let str = ` HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> Bookmarks Bookmarks ` let loop = (root) => { let str = '' root.forEach((item) => { if (item.folder) { str += `${item.toolbar ? `PERSONAL_TOOLBAR_FOLDER="true"` : ''}>${item.name}
` str += loop(item.children) str += ` ` } else { str += ` HREF="${item.url}">${item.name} ` } }) return str } str += loop(bookmarks) str += ` ` return str}ES6之前的就需要顯式的拼接上換行符:
function createBookmarksStr (bookmarks) { var str = '\n\n\nBookmarks\nBookmarks
\n\n\t\n\t\t
\n\t\t\t\u4E66\u7B7E\u680F
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t'
var loop = function (root) { var str = '' root.forEach(function (item) { if (item.folder) { str += '\n\t\t\t\t\t\t+ (item.toolbar ? 'PERSONAL_TOOLBAR_FOLDER="true"' : '') +'>'+item.name+'
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t'
str += loop(item.children) str += '\n\t\t\t\t\t\t\n\t\t\t'
} else { str += '+item.url+'\">'+item.name+'\n\t\t\t\t\t\t\t\t' } }) return str } str += loop(bookmarks) str += '\n\t\t\t\n\n
'
return str}看完了如何生成,接下來看一下如何解析,解析和拼接類似,也是通過深度優先進行遍歷,只是會有一些特征判斷。字符串如何轉化成一棵樹,最簡單的肯定是先轉換為DOM元素,然后再通過操作DOM的api來進行遍歷,有一些庫可以用來做這件事,不過這里直接用的是iframe:
function getBookmarksStrRootNode (str) { // 創建iframe let iframe = document.createElement('iframe') document.body.appendChild(iframe) iframe.style.display = 'none' // 添加書簽dom字符串 iframe.contentWindow.document.documentElement.innerHTML = str // 獲取書簽樹根節點 return iframe.contentWindow.document.querySelector('dl')}function analysisBookmarksStr(str) { let root = getBookmarksStrRootNode(str)}看一下轉換的結果:
書簽DOM字符串:
轉換后的DOM節點:
獲取到書簽樹的根節點,接下來遞歸遍歷即可:
function walkBookmarksTree (root) { let result = [] // 深度優先遍歷 let walk = (node, list) => { let els = node.children if (els && els.length > 0) { for (let i = 0; i < els.length; i++) { let item = els[i] // p標簽或h3標簽直接跳過 if (item.tagName === 'P' || item.tagName === 'H3') { continue } // 文件夾不用創建元素 if (item.tagName === 'DL') { walk(els[i], list) } else {// DT節點 let child = null // 判斷是否是文件夾 let children = item.children let isDir = false for(let j = 0; j < children.length; j++) { if (children[j].tagName === 'H3' || children[j].tagName === 'DL') { isDir = true } } // 文件夾 if (isDir) { child = { name: item.tagName === 'DT' ? item.querySelector('h3') ? item.querySelector('h3').innerText : '' : '', folder: true, children: [] } walk(els[i], child.children) } else {// 書簽 let _item = item.querySelector('a') child = { name: _item.innerText, url: _item.href } } list.push(child) } } } } walk(root, result) return result}function analysisBookmarksStr(str) { let root = getBookmarksStrRootNode(str) let result = walkBookmarksTree(root)}最后解析的結果:
搞定收工,趕緊去試試吧。
總結
以上是生活随笔為你收集整理的xml显示浏览器标签_浅析浏览器书签的导入和导出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: http在链接中加入用户名_爬虫基础——
- 下一篇: 卡片的sak为不支持的类型_“师傅”两字