From 69d9678735418cf06253b7f4aa44021b4ab72e34 Mon Sep 17 00:00:00 2001 From: Pat Nakajima Date: Sun, 28 Apr 2024 13:27:32 -0700 Subject: [PATCH] Add ability to list attributes for an element --- Sources/Kanna/Kanna.swift | 1 + Sources/Kanna/libxmlHTMLNode.swift | 19 +++++++++++++++++++ Tests/KannaTests/KannaTutorialsTest.swift | 12 ++++++++++++ 3 files changed, 32 insertions(+) diff --git a/Sources/Kanna/Kanna.swift b/Sources/Kanna/Kanna.swift index 4d507cb..1454071 100755 --- a/Sources/Kanna/Kanna.swift +++ b/Sources/Kanna/Kanna.swift @@ -164,6 +164,7 @@ XMLElement */ public protocol XMLElement: SearchableNode { var parent: XMLElement? { get set } + var attributes: [String: String?] { get } subscript(attr: String) -> String? { get set } func addPrevSibling(_ node: XMLElement) diff --git a/Sources/Kanna/libxmlHTMLNode.swift b/Sources/Kanna/libxmlHTMLNode.swift index 6e2a406..8b65777 100755 --- a/Sources/Kanna/libxmlHTMLNode.swift +++ b/Sources/Kanna/libxmlHTMLNode.swift @@ -138,6 +138,25 @@ final class libxmlHTMLNode: XMLElement { } } + var attributes: [String : String?] { + var result: [String: String?] = [:] + var attribute = nodePtr.pointee.properties + + while let attr = attribute { + let mem = attr.pointee + let prefix = mem.ns.flatMap { $0.pointee.prefix.string } + let attributeName = [prefix, mem.name.string].compactMap { $0 }.joined(separator: ":") + + if let children = mem.children { + result[attributeName] = libxmlGetNodeContent(children) + } + + attribute = attr.pointee.next + } + + return result + } + init(document: XMLDocument?, docPtr: xmlDocPtr) throws { self.weakDocument = document self.docPtr = docPtr diff --git a/Tests/KannaTests/KannaTutorialsTest.swift b/Tests/KannaTests/KannaTutorialsTest.swift index da79052..cdb5867 100644 --- a/Tests/KannaTests/KannaTutorialsTest.swift +++ b/Tests/KannaTests/KannaTutorialsTest.swift @@ -196,6 +196,18 @@ class KannaTutorialsTests: XCTestCase { XCTAssert(doc.body?.toHTML == TestModifyHTML) } + + func testListAttributes() throws { + let html = """ + +

Three's Company

+ + """ + + let document = try HTML(html: html, encoding: .utf8) + let h2 = document.at_css("h2")! + XCTAssertEqual(["class": "show-title", "data-hello": "world"], h2.attributes) + } } extension KannaTutorialsTests {