Skip to content

Commit baa795a

Browse files
author
tid
committed
init
0 parents  commit baa795a

4 files changed

Lines changed: 303 additions & 0 deletions

File tree

HTMLNode.swift

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
/**@file
2+
* @brief Swift-HTML-Parser
3+
* @author _tid_
4+
*/
5+
6+
/**
7+
* HTMLNode
8+
*/
9+
class HTMLNode {
10+
enum HTMLNodeType : String {
11+
case HTMLUnkownNode = ""
12+
case HTMLHrefNode = "href"
13+
case HTMLTextNode = "text"
14+
case HTMLCodeNode = "code"
15+
case HTMLSpanNode = "span"
16+
case HTMLPNode = "p"
17+
case HTMLLiNode = "li"
18+
case HTMLUiNode = "ui"
19+
case HTMLImageNode = "image"
20+
case HTMLOlNode = "ol"
21+
case HTMLStrongNode = "strong"
22+
case HTMLPreNode = "pre"
23+
case HTMLBlockQuoteNode = "blockquote"
24+
}
25+
26+
var doc : htmlDocPtr
27+
var node : xmlNode?
28+
let nodeType : HTMLNodeType = HTMLNodeType.HTMLUnkownNode
29+
30+
/**
31+
* 親ノード
32+
*/
33+
var parent : HTMLNode? {
34+
if let p = self.node?.parent {
35+
return HTMLNode(doc: self.doc, node: p)
36+
}
37+
return nil
38+
}
39+
40+
/**
41+
* 次ノード
42+
*/
43+
var next : HTMLNode? {
44+
if let n : UnsafePointer<xmlNode> = node?.next {
45+
if n {
46+
return HTMLNode(doc: doc, node: n)
47+
}
48+
}
49+
return nil
50+
}
51+
52+
/**
53+
* 子ノード
54+
*/
55+
var child : HTMLNode? {
56+
if let c = node?.children {
57+
if c {
58+
return HTMLNode(doc: doc, node: c)
59+
}
60+
}
61+
return nil
62+
}
63+
64+
/**
65+
* クラス名
66+
*/
67+
var className : String {
68+
return getAttributeNamed("class")
69+
}
70+
71+
/**
72+
* タグ名
73+
*/
74+
var tagName : String {
75+
if node {
76+
return ConvXmlCharToString(self.node!.name)
77+
}
78+
return ""
79+
}
80+
81+
/**
82+
* コンテンツ
83+
*/
84+
var contents : String {
85+
if node {
86+
var n = self.node!.children
87+
if n {
88+
return ConvXmlCharToString(n.memory.content)
89+
}
90+
}
91+
return ""
92+
}
93+
94+
/**
95+
* Initializer
96+
* @param[in] doc xmlDoc
97+
*/
98+
init(doc: htmlDocPtr = nil) {
99+
self.doc = doc
100+
var node = xmlDocGetRootElement(doc)
101+
if node {
102+
self.node = node.memory
103+
}
104+
}
105+
106+
init(doc: htmlDocPtr, node: UnsafePointer<xmlNode>) {
107+
self.doc = doc
108+
self.node = node.memory
109+
110+
if let type = HTMLNodeType.fromRaw(tagName) {
111+
nodeType = type
112+
}
113+
}
114+
115+
/**
116+
* 属性名を取得する
117+
* @param[in] name 属性
118+
* @return 属性名
119+
*/
120+
func getAttributeNamed(name: String) -> String {
121+
for var attr : xmlAttrPtr = node!.properties; attr; attr = attr.memory.next {
122+
if attr {
123+
var mem = attr.memory
124+
125+
if name == ConvXmlCharToString(mem.name) {
126+
return ConvXmlCharToString(mem.children.memory.content)
127+
}
128+
}
129+
}
130+
131+
return ""
132+
}
133+
134+
/**
135+
* タグ名に一致する全ての子ノードを探す
136+
* @param[in] tagName タグ名
137+
* @return 子ノードの配列
138+
*/
139+
func findChildTags(tagName: String) -> HTMLNode[] {
140+
var nodes : HTMLNode[] = []
141+
142+
return findChildTags(tagName, node: self.child, retAry: &nodes)
143+
}
144+
145+
func findChildTags(tagName: String, node: HTMLNode?, inout retAry: HTMLNode[] ) -> HTMLNode[] {
146+
if node {
147+
for n in node! {
148+
if n.tagName == tagName {
149+
retAry.append(n)
150+
}
151+
152+
findChildTags(tagName, node: n.child, retAry: &retAry)
153+
}
154+
}
155+
return retAry
156+
}
157+
158+
/**
159+
* タグ名で子ノードを探す
160+
* @param[in] tagName タグ名
161+
* @return 子ノード。見つからなければnil
162+
*/
163+
func findChildTag(tagName: String) -> HTMLNode? {
164+
return findChildTag(tagName, node: self)
165+
}
166+
167+
func findChildTag(tagName: String, node: HTMLNode?) -> HTMLNode? {
168+
if node == nil {
169+
return nil
170+
}
171+
172+
for curNode in node! {
173+
if tagName == curNode.tagName {
174+
return curNode
175+
}
176+
177+
if let c = curNode.child {
178+
if let n = findChildTag(tagName, node: c) {
179+
return n
180+
}
181+
}
182+
}
183+
184+
return nil
185+
}
186+
}
187+
188+
extension HTMLNode : Sequence {
189+
func generate() -> HTMLNodeGenerator {
190+
return HTMLNodeGenerator(node: self)
191+
}
192+
}
193+
194+
/**
195+
* HTMLNodeGenerator
196+
*/
197+
class HTMLNodeGenerator : Generator {
198+
var node : HTMLNode?
199+
200+
init(node: HTMLNode?) {
201+
self.node = node
202+
}
203+
204+
func next() -> HTMLNode? {
205+
var temp = node?
206+
node = node?.next
207+
return temp
208+
}
209+
}
210+

HTMLParser.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**@file
2+
* @brief Swift-HTML-Parser
3+
* @author _tid_
4+
*/
5+
import Foundation
6+
7+
func ConvXmlCharToString(str: UnsafePointer<xmlChar>) -> String {
8+
if str {
9+
return String.fromCString(UnsafePointer<CChar>(str))
10+
}
11+
return ""
12+
}
13+
14+
/**
15+
* HTMLParser
16+
*/
17+
class HTMLParser {
18+
var _doc : htmlDocPtr = nil
19+
var rootNode : HTMLNode?
20+
21+
/**
22+
* HTML tag
23+
*/
24+
var html : HTMLNode? {
25+
return rootNode?.findChildTag("html")
26+
}
27+
28+
/**
29+
* HEAD tag
30+
*/
31+
var head : HTMLNode? {
32+
return rootNode?.findChildTag("head")
33+
}
34+
35+
/**
36+
* BODY tag
37+
*/
38+
var body : HTMLNode? {
39+
return rootNode?.findChildTag("body")
40+
}
41+
42+
/**
43+
* @param[in] html HTML文字列
44+
* @param[in] error エラーがあれば返します
45+
*/
46+
init(html: String, inout error: NSError?) {
47+
if html.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 0 {
48+
var cfenc : CFStringEncoding = CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)
49+
var cfencstr : CFStringRef = CFStringConvertEncodingToIANACharSetName(cfenc)
50+
51+
var cur : CChar[]? = html.cStringUsingEncoding(NSUTF8StringEncoding)
52+
var url : CString = ""
53+
var enc : CString = CFStringGetCStringPtr(cfencstr, 0)
54+
let optionHtml : CInt = 1
55+
56+
if var ucur = cur {
57+
var temp : CMutablePointer<CChar> = &ucur
58+
var aaa = UnsafePointer<CUnsignedChar>(temp.value)
59+
_doc = htmlReadDoc(aaa, url, enc, optionHtml)
60+
rootNode = HTMLNode(doc: _doc)
61+
}
62+
} else {
63+
error = NSError(domain: "HTMLParserdomain", code: 1, userInfo: nil)
64+
}
65+
}
66+
67+
deinit {
68+
xmlFreeDoc(_doc)
69+
}
70+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//
2+
// Use this file to import your target's public headers that you would like to expose to Swift.
3+
//
4+
5+
#import <libxml/HTMLtree.h>

main.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Foundation
2+
3+
let html = "<ul><li><input type='image' name='input1' value='string1value' class='abc' /></li><li><input type='image' name='input2' value='string2value' class='def' /></li></ul><span class='spantext'><b>Hello World 1</b></span><span class='spantext'><b>Hello World 2</b></span>"
4+
5+
var err : NSError?
6+
var parser = HTMLParser(html: html, error: &err)
7+
if err {
8+
println(err)
9+
exit(1)
10+
}
11+
12+
var bodyNode = parser.body
13+
14+
if let inputNodes = bodyNode?.findChildTags("b") {
15+
for node in inputNodes {
16+
println(node.contents)
17+
}
18+
}

0 commit comments

Comments
 (0)