Andy Fedoroff Andy Fedoroff - 1 month ago 12
Swift Question

The best way to format data for writing to XML in macOS using Swift

I'd like to create an XML document like this:

<prefs>
<exactmap>
<map>
(UCS point_1 : x = 50.0, y = 50.0)
(UCS point_2 : x = 300.0, y = 200.0)
(UCS point_3 : x = 200.0, y = 400.0)
(UCS point_4 : x = 300.0, y = 300.0)
</map>
</exactmap>
</prefs>


I wrote a code and it looks like a mess))

let writeToXMLDoc: NSString = "<prefs>\n\t<exactmap>\n\t\t<map>\n\t\t\t//(UCS point_1 : x = 50.0, y = 50.0 )\n\t\t\t(UCS point_2 : x = 300.0, y = 200.0 )\n\t\t\t(UCS point_3 : x = 200.0, y = 400.0 )\n\t\t\t(UCS point_4 : x = 300.0, y = 300.0 )\n\t\t</map>\n\t</exactmap>\n</prefs>"


How to make it more readable in Swift? Is there a possible way to create a separate XML-formatted file in Xcode project? How to do that?

And in case it's possible to create a separate file, how to feed variables for x and y?

Answer

Your XML structure is wrong. How are you going to read back from the XML file? Your data has now become unstructured.

Play with the code below. It's pretty long because it's XM (sadly)

func xmlAttributeWithName(name: String, value: String) -> NSXMLNode {
    let node = NSXMLNode(kind: .AttributeKind)
    node.name = name
    node.stringValue = value

    return node
}

// Your data
let points = [
    (x: 50.0, y: 50.0),
    (x: 300.0, y: 200.0),
    (x: 200.0, y: 400.0),
    (x: 300.0, y: 300.0)
]

let mapElement = NSXMLElement(name: "map")
for (index, p) in points.enumerate() {
    let pointElement = NSXMLElement(name: "ucs_point")
    pointElement.attributes = [
        xmlAttributeWithName("id", value: "\(index)"),
        xmlAttributeWithName("x", value: "\(p.x)"),
        xmlAttributeWithName("y", value: "\(p.y)")
    ]

    mapElement.addChild(pointElement)
}

let exactMapElement = NSXMLElement(name: "exactmap")
exactMapElement.addChild(mapElement)

let prefsElement = NSXMLElement(name: "prefs")
prefsElement.addChild(exactMapElement)

let xmlDocument = NSXMLDocument(rootElement: prefsElement)
xmlDocument.characterEncoding = "utf-8"
xmlDocument.version = "1.0"

let xmlOptions = NSXMLNodePrettyPrint | NSXMLNodeCompactEmptyElement
let xmlString = xmlDocument.XMLStringWithOptions(xmlOptions)
try! xmlString.writeToFile("/path/to/file.xml", atomically: true, encoding: NSUTF8StringEncoding)

Result:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<prefs>
    <exactmap>
        <map>
            <ucs_point id="0" x="50.0" y="50.0"/>
            <ucs_point id="1" x="300.0" y="200.0"/>
            <ucs_point id="2" x="200.0" y="400.0"/>
            <ucs_point id="3" x="300.0" y="300.0"/>
        </map>
    </exactmap>
</prefs>