Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shouldProcessNamespaces decoder property #81

Merged
merged 1 commit into from Feb 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 18 additions & 7 deletions Sources/XMLCoder/Auxiliaries/XMLStackParser.swift
Expand Up @@ -12,18 +12,29 @@ class XMLStackParser: NSObject {
var root: XMLCoderElement?
private var stack: [XMLCoderElement] = []

static func parse(with data: Data,
errorContextLength length: UInt) throws -> KeyedBox {
static func parse(
with data: Data,
errorContextLength length: UInt,
shouldProcessNamespaces: Bool
) throws -> KeyedBox {
let parser = XMLStackParser()

let node = try parser.parse(with: data, errorContextLength: length)
let node = try parser.parse(
with: data,
errorContextLength: length,
shouldProcessNamespaces: shouldProcessNamespaces
)

return node.flatten()
}

func parse(with data: Data,
errorContextLength: UInt) throws -> XMLCoderElement {
func parse(
with data: Data,
errorContextLength: UInt,
shouldProcessNamespaces: Bool
) throws -> XMLCoderElement {
let xmlParser = XMLParser(data: data)
xmlParser.shouldProcessNamespaces = shouldProcessNamespaces
xmlParser.delegate = self

guard !xmlParser.parse(), root == nil else {
Expand Down Expand Up @@ -92,8 +103,8 @@ extension XMLStackParser: XMLParserDelegate {

func parser(_: XMLParser,
didStartElement elementName: String,
namespaceURI _: String?,
qualifiedName _: String?,
namespaceURI: String?,
qualifiedName: String?,
attributes attributeDict: [String: String] = [:]) {
let element = XMLCoderElement(key: elementName, attributes: attributeDict)
stack.append(element)
Expand Down
8 changes: 7 additions & 1 deletion Sources/XMLCoder/Decoder/XMLDecoder.swift
Expand Up @@ -245,6 +245,11 @@ open class XMLDecoder {
/// span more than a few lines.
open var errorContextLength: UInt = 0

/** A boolean value that determines whether the parser reports the
namespaces and qualified names of elements. The default value is `false`.
*/
open var shouldProcessNamespaces: Bool = false

/// Options set on the top-level encoder to pass down the decoding hierarchy.
struct Options {
let dateDecodingStrategy: DateDecodingStrategy
Expand Down Expand Up @@ -283,7 +288,8 @@ open class XMLDecoder {
) throws -> T {
let topLevel: Box = try XMLStackParser.parse(
with: data,
errorContextLength: errorContextLength
errorContextLength: errorContextLength,
shouldProcessNamespaces: shouldProcessNamespaces
)

let decoder = XMLDecoderImplementation(referencing: topLevel, options: options)
Expand Down
14 changes: 10 additions & 4 deletions Tests/XMLCoderTests/Auxiliary/XMLStackParserTests.swift
Expand Up @@ -21,8 +21,11 @@ class XMLStackParserTests: XCTestCase {
"""
let xmlData = xmlString.data(using: .utf8)!

let root: XMLCoderElement? = try parser.parse(with: xmlData,
errorContextLength: 0)
let root: XMLCoderElement? = try parser.parse(
with: xmlData,
errorContextLength: 0,
shouldProcessNamespaces: false
)

let expected = XMLCoderElement(
key: "container",
Expand All @@ -46,7 +49,10 @@ class XMLStackParserTests: XCTestCase {
let xmlString = "lorem ipsum"
let xmlData = xmlString.data(using: .utf8)!

XCTAssertThrowsError(try parser.parse(with: xmlData,
errorContextLength: 0))
XCTAssertThrowsError(try parser.parse(
with: xmlData,
errorContextLength: 0,
shouldProcessNamespaces: false
))
}
}
38 changes: 38 additions & 0 deletions Tests/XMLCoderTests/NamespaceTest.swift
@@ -0,0 +1,38 @@
//
// NamespaceTest.swift
// XMLCoder
//
// Created by Max Desiatov on 27/02/2019.
//

import Foundation
import XCTest
@testable import XMLCoder

private let xmlData = """
<h:table xmlns:h="http://www.w3.org/TR/html4/">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
""".data(using: .utf8)!

private struct Table: Codable, Equatable {
struct TR: Codable, Equatable {
let td: [String]
}

let tr: TR
}

class NameSpaceTest: XCTestCase {
func testDecoder() throws {
let decoder = XMLDecoder()
decoder.shouldProcessNamespaces = true

let decoded = try decoder.decode(Table.self, from: xmlData)

XCTAssertEqual(decoded, Table(tr: .init(td: ["Apples", "Bananas"])))
}
}
4 changes: 4 additions & 0 deletions XMLCoder.xcodeproj/project.pbxproj
Expand Up @@ -86,6 +86,7 @@
D14D8A8621F1D6B300B0D31A /* SingleChildTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D14D8A8521F1D6B300B0D31A /* SingleChildTests.swift */; };
D162674321F9B2AF0056D1D8 /* OptionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D162674121F9B2850056D1D8 /* OptionalTests.swift */; };
D1CB1EF521EA9599009CAF02 /* RJITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_37 /* RJITest.swift */; };
D1CFC8242226B13F00B03222 /* NamespaceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1CFC8222226AFB400B03222 /* NamespaceTest.swift */; };
D1E0C85321D8E65E0042A261 /* ErrorContextTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E0C85121D8E6540042A261 /* ErrorContextTest.swift */; };
D1E0C85521D91EBF0042A261 /* Metatypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E0C85421D91EBF0042A261 /* Metatypes.swift */; };
D1FC040521C7EF8200065B43 /* RJISample.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1FC040421C7EF8200065B43 /* RJISample.swift */; };
Expand Down Expand Up @@ -198,6 +199,7 @@
D11979B721F5EA5400A9C574 /* XMLCoder.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XMLCoder.podspec; sourceTree = "<group>"; };
D14D8A8521F1D6B300B0D31A /* SingleChildTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleChildTests.swift; sourceTree = "<group>"; };
D162674121F9B2850056D1D8 /* OptionalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalTests.swift; sourceTree = "<group>"; };
D1CFC8222226AFB400B03222 /* NamespaceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NamespaceTest.swift; sourceTree = "<group>"; };
D1E0C85121D8E6540042A261 /* ErrorContextTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorContextTest.swift; sourceTree = "<group>"; };
D1E0C85421D91EBF0042A261 /* Metatypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metatypes.swift; sourceTree = "<group>"; };
D1FC040421C7EF8200065B43 /* RJISample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RJISample.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -384,6 +386,7 @@
B3BE1D602202C1F600259831 /* DynamicNodeEncodingTest.swift */,
A61DCCD621DF8DB300C0A19D /* ClassTests.swift */,
D14D8A8521F1D6B300B0D31A /* SingleChildTests.swift */,
D1CFC8222226AFB400B03222 /* NamespaceTest.swift */,
);
name = XMLCoderTests;
path = Tests/XMLCoderTests;
Expand Down Expand Up @@ -625,6 +628,7 @@
D1FC040521C7EF8200065B43 /* RJISample.swift in Sources */,
BF63EF0A21CD7C1A001D38C5 /* URLTests.swift in Sources */,
BF9457CE21CBB516005ACFDE /* StringBoxTests.swift in Sources */,
D1CFC8242226B13F00B03222 /* NamespaceTest.swift in Sources */,
BF9457D021CBB516005ACFDE /* UIntBoxTests.swift in Sources */,
OBJ_80 /* BooksTest.swift in Sources */,
OBJ_81 /* BreakfastTest.swift in Sources */,
Expand Down