Skip to content

Commit 2b1253e

Browse files
authored
Encode element with empty key, empty element, and attributes (#223)
Fixes an edge case with intrinsic value key encoding.
1 parent 487ece5 commit 2b1253e

2 files changed

Lines changed: 79 additions & 5 deletions

File tree

Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,16 @@ struct XMLCoderElement: Equatable {
217217
_ string: inout String,
218218
_ charactersEscapedInAttributes: [(String, String)]
219219
) {
220+
let attributesBelongingToContainer = self.elements.filter {
221+
$0.key.isEmpty && !$0.attributes.isEmpty
222+
}.flatMap {
223+
$0.attributes
224+
}
225+
let allAttributes = self.attributes + attributesBelongingToContainer
226+
220227
let attributes = formatting.contains(.sortedKeys) ?
221-
self.attributes.sorted(by: { $0.key < $1.key }) :
222-
self.attributes
228+
allAttributes.sorted(by: { $0.key < $1.key }) :
229+
allAttributes
223230
formatXMLAttributes(
224231
from: attributes,
225232
into: &string,
@@ -266,10 +273,9 @@ struct XMLCoderElement: Equatable {
266273

267274
if !key.isEmpty {
268275
string += "<\(key)"
276+
formatXMLAttributes(formatting, &string, escapedCharacters.attributes)
269277
}
270278

271-
formatXMLAttributes(formatting, &string, escapedCharacters.attributes)
272-
273279
if !elements.isEmpty {
274280
let prettyPrintElements = prettyPrinted && !containsTextNodes
275281
if !key.isEmpty {
@@ -282,7 +288,9 @@ struct XMLCoderElement: Equatable {
282288
string += "</\(key)>"
283289
}
284290
} else {
285-
string += " />"
291+
if !key.isEmpty {
292+
string += " />"
293+
}
286294
}
287295

288296
return string

Tests/XMLCoderTests/Auxiliary/XMLElementTests.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,70 @@ class XMLElementTests: XCTestCase {
6464
XCTAssert(whitespaceElement2.isWhitespaceWithNoElements())
6565
XCTAssert(whitespaceElement3.isWhitespaceWithNoElements())
6666
}
67+
68+
func testNestedElementWith_Namespace_Attribute() {
69+
typealias Attribute = XMLCoderElement.Attribute
70+
typealias Element = XMLCoderElement
71+
let nested = Element(key: "Nested",
72+
elements: [
73+
Element(key: "",
74+
elements: [],
75+
attributes: [
76+
Attribute(key: "xsi:someName", value: "nestedAttrValue")
77+
]
78+
)],
79+
attributes: [
80+
Attribute(key: "xmlns:xsi", value: "https://example.com")
81+
])
82+
let inputNamespace = Attribute(key: "xmlns", value: "https://example.com")
83+
let input = Element(key: "Input",
84+
elements: [nested],
85+
attributes: [inputNamespace])
86+
87+
let result = input.toXMLString(
88+
escapedCharacters: (elements: XMLEncoder().charactersEscapedInElements,
89+
attributes: XMLEncoder().charactersEscapedInAttributes),
90+
formatting: [],
91+
indentation: .spaces(4)
92+
)
93+
94+
XCTAssertEqual(result, """
95+
<Input xmlns="https://example.com"><Nested xmlns:xsi="https://example.com" xsi:someName="nestedAttrValue"></Nested></Input>
96+
""")
97+
}
98+
99+
func testNestedElementWith_Namespace_Attribute_Element() {
100+
typealias Attribute = XMLCoderElement.Attribute
101+
typealias Element = XMLCoderElement
102+
let nested = Element(key: "Nested",
103+
elements: [
104+
Element(key: "",
105+
elements: [
106+
Element(key: "nonAttrField",
107+
elements: [Element(key: "", stringValue: "hello")],
108+
attributes: [])
109+
],
110+
attributes: [
111+
Attribute(key: "xsi:someName", value: "nestedAttrValue")
112+
]
113+
)],
114+
attributes: [
115+
Attribute(key: "xmlns:xsi", value: "https://example.com")
116+
])
117+
let inputNamespace = Attribute(key: "xmlns", value: "https://example.com")
118+
let input = Element(key: "Input",
119+
elements: [nested],
120+
attributes: [inputNamespace])
121+
122+
let result = input.toXMLString(
123+
escapedCharacters: (elements: XMLEncoder().charactersEscapedInElements,
124+
attributes: XMLEncoder().charactersEscapedInAttributes),
125+
formatting: [],
126+
indentation: .spaces(4)
127+
)
128+
129+
XCTAssertEqual(result, """
130+
<Input xmlns="https://example.com"><Nested xmlns:xsi="https://example.com" xsi:someName="nestedAttrValue"><nonAttrField>hello</nonAttrField></Nested></Input>
131+
""")
132+
}
67133
}

0 commit comments

Comments
 (0)