激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 詳解Python中DOM方法的動態性

詳解Python中DOM方法的動態性

2020-06-04 09:15腳本之家 Python

這篇文章主要介紹了詳解Python中DOM方法的動態性,xml.dom模塊在Python的網絡編程中相當有用,本文來自于IBM官網的開發者技術文檔,需要的朋友可以參考下

文檔對象模型

xml.dom 模塊對于 Python 程序員來說,可能是使用 XML 文檔時功能最強大的工具。不幸的是,XML-SIG 提供的文檔目前來說還比較少。W3C 語言無關的 DOM 規范填補了這方面的部分空白。但 Python 程序員最好有一個特定于 Python 語言的 DOM 的快速入門指南。本文旨在提供這樣一個指南。在 上一篇專欄文章 中,某些樣本中使用了樣本 quotations.dtd 文件,并且這些文件可以與本文中的代碼樣本檔案文件一起使用。

有必要了解 DOM 的確切含義。這方面,正式解釋非常好:

    “文檔對象模型”是平臺無關和語言無關的接口,它允許程序和腳本動態訪問和更新文檔的內容、結構和樣式。可以進一步處理文檔,而處理的結果也可以合并到已顯示的頁面中。(萬維網聯盟 DOM 工作組)

DOM 將 XML 文檔轉換成樹 -- 或森林 -- 表示。萬維網聯盟 (W3C) 規范給出了一個 HTML 表的 DOM 版本作為例子。

詳解Python中DOM方法的動態性

如上圖所示,DOM 從一個更加抽象的角度定義了一組可以遍歷、修剪、改組、輸出和操作樹的方法,而這種方法要比 XML 文檔的線性表示更為便利。

將 HTML 轉換成 XML

有效的 HTML 幾乎就是有效的 XML,但又不完全相同。這里有兩個主要的差異,XML 標記是區分大小寫的,并且所有 XML 標記都需要一個顯式的結束符號(作為結束標記,而這對于某些 HTML 標記是可選的;例如: <img src="X.png" /> )。使用 xml.dom 的一個簡單示例就是使用 HtmlBuilder() 類將 HTML 轉換成 XML。
try_dom1.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
"""Convert a valid HTML document to XML
  USAGE: python try_dom1.py < infile.html > outfile.xml
"""
    
    
import
    
     sys
    
    from
    
     xml.dom
    
    import
    
     core
    
    from
    
     xml.dom.html_builder
    
    import
    
     HtmlBuilder
    
    # Construct an HtmlBuilder object and feed the data to it
b = HtmlBuilder()
b.feed(sys.stdin.read())
    
    # Get the newly-constructed document object
doc = b.document
    
    # Output it as XML
    
    
print
    
     doc.toxml()

HtmlBuilder() 類很容易實現它繼承的部分基本 xml.dom.builder 模板的功能,它的源碼值得研究。然而,即使我們自己實現了模板功能,DOM 程序的輪廓還是相似的。在一般情況下,我們將用一些方法構建一個 DOM 實例,然后對該實例進行操作。DOM 實例的 .toxml() 方法是一種生成 DOM 實例的字符串表示的簡單方法(在以上的情況中,只要在生成后將它打印出來)。

將 Python 對象轉換成 XML

Python 程序員可以通過將任意 Python 對象導出為 XML 實例來實現相當多的功能和通用性。這就允許我們以習慣的方式來處理 Python 對象,并且可以選擇最終是否使用實例屬性作為生成 XML 中的標記。只需要幾行(從 building.py 示例派生出),我們就可以將 Python“原生”對象轉換成 DOM 對象,并對包含對象的那些屬性執行遞歸處理。
try_dom2.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
"""Build a DOM instance from scratch, write it to XML
  USAGE: python try_dom2.py > outfile.xml
"""
    
    
import
    
     types
    
    from
    
     xml.dom
    
    import
    
     core
    
    from
    
     xml.dom.builder
    
    import
    
     Builder
    
    # Recursive function to build DOM instance from Python instance
    
    
defobject_convert
    
    (builder, inst):
  
    
    # Put entire object inside an elem w/ same name as the class.
  builder.startElement(inst.__class__.__name__)
  
    
    for
    
     attr
    
    in
    
     inst.__dict__.keys():
    
    
    if
    
     attr[0] ==
    
    '_':  
    
    # Skip internal attributes
              
     
     continue
    
    
    value = getattr(inst, attr)
    
    
    if
    
     type(value) == types.InstanceType:
      
    
    # Recursively process subobjects
      object_convert(builder, value)
    
    
    else
    
    :
      
    
    # Convert anything else to string, put it in an element
      builder.startElement(attr)
      builder.text(str(value))
      builder.endElement(attr)
  builder.endElement(inst.__class__.__name__)
    
    if
    
     __name__ ==
    
    '__main__':
  
    
    # Create container classes
    
    
  classquotations
    
    :
    
    pass
  classquotation
    
    :
    
    pass
    # Create an instance, fill it with hierarchy of attributes
    
    
  inst = quotations()
  inst.title =
    
    "Quotations file (not quotations.dtd conformant)"
  inst.quot1 = quot1 = quotation()
  quot1.text =
    
    """'"is not a quine" is not a quine' is a quine"""
  quot1.source =
    
    "Joshua Shagam, kuro5hin.org"
  inst.quot2 = quot2 = quotation()
  quot2.text =
    
    "Python is not a democracy. Voting doesn't help. "+\
         
    
    "Crying may..."
  quot2.source =
    
    "Guido van Rossum, comp.lang.python"
    
    
 
     # Create the DOM Builder
  builder = Builder()
  object_convert(builder, inst)
  
    
    print
    
     builder.document.toxml()

函數 object_convert() 有一些限制。例如,不可能用以上的過程生成符合 XML 文檔的 quotations.dtd:#PCDATA 文本不能直接放到 quotation 類中,而只能放到類的屬性中(如 .text )。一個簡單的變通方法就是讓 object_convert() 以特殊方式處理一個帶有名稱的屬性,例如 .PCDATA 。可以用各種方法使對 DOM 的轉換變得更巧妙,但該方法的妙處在于我們可以從整個 Python 對象開始,以簡明的方式將它們轉換成 XML 文檔。

還應值得注意的是在生成的 XML 文檔中,處于同一個級別的元素沒有什么明顯的順序關系。例如,在作者的系統中使用特定版本的 Python,源碼中定義的第二個 quotation 在輸出中卻第一個出現。但這種順序關系在不同的版本和系統之間會改變。Python 對象的屬性并不是按固定順序排列的,因此這種特性就具有意義。對于與數據庫系統相關的數據,我們希望它們具有這種特性,但是對于標記為 XML 的文章卻顯然不希望具有這種特性(除非我們想要更新 William Burroughs 的 "cut-up" 方法)。

將 XML 文檔轉換成 Python 對象

從 XML 文檔生成 Python 對象就像其逆向過程一樣簡單。在多數情況下,用 xml.dom 方法就可以了。但在某些情況下,最好使用與處理所有“類屬”Python 對象相同的技術來處理從 XML 文檔生成的對象。例如,在以下的代碼中,函數 pyobj_printer() 也許是已經用來處理任意 Python 對象的函數。
try_dom3.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
"""Read in a DOM instance, convert it to a Python object
"""
    
    
from
    
     xml.dom.utils
    
    import
    
     FileReader
    
    classPyObject
    
    :
    
    pass
defpyobj_printer
    
    (py_obj, level=0):
  
    
    """Return a "deep" string description of a Python object"""
     
     
     from
     
     
    
     string
    
    import
    
     join, split
  
    
    import
    
     types
  descript =
    
    ''
     
     
     for
     
     
    
     membname
    
    in
    
     dir(py_obj):
    member = getattr(py_obj,membname)
    
    
    if
    
     type(member) == types.InstanceType:
      descript = descript + (
    
    ' '*level) +
    
    '{'+membname+
    
    '}\n'
      descript = descript + pyobj_printer(member, level+3)
    
    
    elif
    
     type(member) == types.ListType:
      descript = descript + (
    
    ' '*level) +
    
    '['+membname+
    
    ']\n'
             
     
     for
     
     
    
     i
    
    in
    
     range(len(member)):
        descript = descript+(
    
    ' '*level)+str(i+1)+
    
    ': '+ \
              pyobj_printer(member[i],level+3)
    
    
    else
    
    :
      descript = descript + membname+
    
    '='
      descript = descript + join(split(str(member)[:50]))+
    
    '...\n'
     
     
     return
     
     
    
     descript
    
    defpyobj_from_dom
    
    (dom_node):
  
    
    """Converts a DOM tree to a "native" Python object"""
  py_obj = PyObject()
  py_obj.PCDATA =
    
    ''
     
     
     for
     
     
    
     node
    
    in
    
     dom_node.get_childNodes():
    
    
    if
    
     node.name ==
    
    '#text':
      py_obj.PCDATA = py_obj.PCDATA + node.value
    
    
    elif
    
     hasattr(py_obj, node.name):
      getattr(py_obj, node.name).append(pyobj_from_dom(node))
    
    
    else
    
    :
      setattr(py_obj, node.name, [pyobj_from_dom(node)])
  
    
    return
    
     py_obj
    
    # Main test
dom_obj = FileReader(
    
    "quotes.xml").document
py_obj = pyobj_from_dom(dom_obj)
    
    if
    
     __name__ ==
    
    "__main__":
  
    
    print
    
     pyobj_printer(py_obj)

這里的關注焦點應該是函數 pyobj_from_dom() ,特別是起實際作用的 xml.dom 方法 .get_childNodes() 。在 pyobj_from_dom() 中,我們直接抽取標記之間的所有文本,將它放到保留屬性 .PCDATA 中。對于任何遇到的嵌套標記,我們創建一個新屬性,其名稱與標記匹配,并將一個列表分配給該屬性,這樣就可以潛在地包含在在父代塊中多次出現的標記。當然,使用列表要維護在 XML 文檔中遇到的標記的順序。

除了使用舊的 pyobj_printer() 類屬函數(或者,更復雜和健壯的函數)之外,我們可以使用正常的屬性記號來訪問 py_obj 的元素。
Python 交互式會話

?
1
2
3
4
5
6
7
8
9
10
11
12
>>>
    
    from
    
     try_dom3
    
    import
    
     *
>>> py_obj.quotations[0].quotation[3].source[0].PCDATA
    
    'Guido van Rossum, '

重新安排 DOM 樹

DOM 的一大優點是它可以讓程序員以非線性方式對 XML 文檔進行操作。由相匹配的開/關標記括起的每一塊都只是 DOM 樹中的一個“節點”。當以類似于列表的方式維護節點以保留順序信息時,則順序并沒有什么特殊之處,也并非不可改變。我們可以輕易地剪下某個節點,嫁接到 DOM 樹的另一個位置(如果 DTD 允許,甚至嫁接到另一層上)。或者添加新的節點、刪除現有節點,等等。
try_dom4.py

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""Manipulate the arrangement of nodes in a DOM object
"""
    
    
from
    
     try_dom3
    
    import
    
     *
    
    #-- Var 'doc' will hold the single <quotations> "trunk"
doc = dom_obj.get_childNodes()[0]
    
    #-- Pull off all the nodes into a Python list
# (each node is a <quotation> block, or a whitespace text node)
nodes = []
    
    while
    
     1:
  
    
    try
    
    : node = doc.removeChild(doc.get_childNodes()[0])
  
    
    except
    
    :
    
    break
    
    
  nodes.append(node)
    
    #-- Reverse the order of the quotations using a list method
# (we could also perform more complicated operations on the list:
# delete elements, add new ones, sort on complex criteria, etc.)
nodes.reverse()
    
    #-- Fill 'doc' back up with our rearranged nodes
    
    
for
    
     node
    
    in
    
     nodes:
  
    
    # if second arg is None, insert is to end of list
  doc.insertBefore(node, None)
    
    #-- Output the manipulated DOM
    
    
print
    
     dom_obj.toxml()

如果我們將 XML 文檔只看作一個文本文件,或者使用一個面向序列的模塊(如 xmllib 或 xml.sax),那么在以上幾行中執行對 quotation 節點的重新安排操作將引出一個值得考慮的問題。然而如果使用 DOM,則問題就如同對 Python 列表執行的任何其它操作一樣簡單。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久人人做 | 欧美国产精品一区二区 | 亚洲视屏在线观看 | 欧美视屏一区二区 | 国产日韩a | 黄污网址 | 欧美精品日日鲁夜夜添 | 蜜桃网站在线 | 亚洲国产成人一区二区 | 天天看夜夜爽 | 欧美黄色一级带 | 亚洲网站免费观看 | 中文字幕在线观看91 | 日本黄色一级电影 | 国产精品一区二区视频 | 高清视频91| 91热久久免费频精品黑人99 | 欧美日韩精品一区二区三区不卡 | 久久亚洲综合色 | 毛片毛片 | 91成人一区 | 日本高清在线免费 | 国产精品亚洲一区二区三区在线观看 | 爱高潮www亚洲精品 国产一区二区三区视频免费 | 久久成人午夜视频 | 黑人操穴 | 成人国产精品齐天大性 | 成人午夜精品久久久久久久3d | 毛片免费视频网站 | 日韩黄色av网站 | 亚洲精品一区二区三区大胸 | 国产精品久久久在线观看 | 亚洲va久久久噜噜噜久久男同 | 欧美一级全黄 | 国产宾馆3p国语对白 | 亚洲精品无码不卡在线播放he | 一级外国毛片 | 欧美 国产 亚洲 卡通 综合 | 久久国产一级片 | 久久久久久久久久久久久国产精品 | 亚洲精品一区中文字幕 |