Skip to content

Commit 42f6238

Browse files
authored
fix: use self-closing tags when children are implictly hidden (#299)
1 parent b2b5d72 commit 42f6238

3 files changed

Lines changed: 34 additions & 10 deletions

File tree

Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ struct XMLCoderElement: Equatable, Sendable {
3636
return key.isEmpty
3737
}
3838

39+
private var isPracticallyEmpty: Bool {
40+
guard stringValue == nil else { return false }
41+
return elements.allSatisfy { $0.key.isEmpty && $0.isPracticallyEmpty }
42+
}
43+
3944
init(
4045
key: String,
4146
elements: [XMLCoderElement] = [],
@@ -313,7 +318,7 @@ struct XMLCoderElement: Equatable, Sendable {
313318
formatXMLAttributes(formatting, &string, escapedCharacters.attributes)
314319
}
315320

316-
if !elements.isEmpty || formatting.contains(.noEmptyElements) {
321+
if !isPracticallyEmpty || formatting.contains(.noEmptyElements) {
317322
let hasOnlyIntrinsicContent = elements.allSatisfy { element in
318323
element.key.isEmpty && !element.elements.contains { !$0.key.isEmpty }
319324
}

Tests/XMLCoderTests/AdvancedFeatures/InlinePropertyTests.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,25 @@ import XCTest
1515
private enum InlineChoice: Equatable, Codable {
1616
case simple(Nested1)
1717
case nested(Nested1, labeled: Nested2)
18-
18+
case attributesOnly(AttributesOnly)
19+
1920
enum CodingKeys: String, CodingKey, XMLChoiceCodingKey {
20-
case simple, nested
21+
case simple, nested, attributesOnly
2122
}
22-
23+
2324
enum SimpleCodingKeys: String, CodingKey { case _0 = "" }
24-
25+
2526
enum NestedCodingKeys: String, CodingKey {
2627
case _0 = ""
2728
case labeled
2829
}
29-
30+
31+
enum AttributesOnlyCodingKeys: String, CodingKey { case _0 = "" }
32+
3033
struct Nested1: Equatable, Codable, DynamicNodeEncoding {
3134
var attr = "n1_a1"
3235
var val = "n1_v1"
33-
36+
3437
public static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
3538
switch key {
3639
case CodingKeys.attr: return .attribute
@@ -42,6 +45,18 @@ private enum InlineChoice: Equatable, Codable {
4245
struct Nested2: Equatable, Codable {
4346
var val = "n2_val"
4447
}
48+
49+
struct AttributesOnly: Equatable, Codable, DynamicNodeEncoding {
50+
var name = "attr"
51+
52+
enum CodingKeys: String, CodingKey {
53+
case name = "Name"
54+
}
55+
56+
public static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
57+
return .attribute
58+
}
59+
}
4560
}
4661

4762
final class InlinePropertyTests: XCTestCase {
@@ -75,9 +90,12 @@ final class InlinePropertyTests: XCTestCase {
7590
encoder.outputFormatting = .prettyPrinted
7691
encoder.prettyPrintIndentation = .spaces(4)
7792

78-
let original: [InlineChoice] = [.nested(.init(), labeled: .init()), .simple(.init())]
93+
let original: [InlineChoice] = [
94+
.nested(.init(), labeled: .init()),
95+
.simple(.init()),
96+
.attributesOnly(.init())
97+
]
7998
let encoded = try encoder.encode(original, withRootKey: "container")
80-
print(String(data: encoded, encoding: .utf8)!)
8199
XCTAssertEqual(
82100
String(data: encoded, encoding: .utf8),
83101
"""
@@ -91,6 +109,7 @@ final class InlinePropertyTests: XCTestCase {
91109
<simple attr="n1_a1">
92110
<val>n1_v1</val>
93111
</simple>
112+
<attributesOnly Name="attr" />
94113
</container>
95114
"""
96115
)

Tests/XMLCoderTests/Auxiliary/XMLElementTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class XMLElementTests: XCTestCase {
9494
)
9595

9696
XCTAssertEqual(result, """
97-
<Input xmlns="https://example.com"><Nested xmlns:xsi="https://example.com" xsi:someName="nestedAttrValue"></Nested></Input>
97+
<Input xmlns="https://example.com"><Nested xmlns:xsi="https://example.com" xsi:someName="nestedAttrValue" /></Input>
9898
""")
9999
}
100100

0 commit comments

Comments
 (0)