XMLMapper
XMLMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from XML.
- Example
- Requirements
- Definition of the protocols
- How to use
- Requests subspec
- Communication
- Installation
- Special thanks
- License
Example
To run the example project, clone the repo, and run pod install
from the Example directory first.
Requirements
- iOS 8.0+ / macOS 10.9+ / tvOS 9.0+ / watchOS 2.0+
- Xcode 9.1+
- Swift 3.1+
Definition of the protocols
XMLBaseMappable
Protocol
var nodeName: String! { get set }
This property is where the name of the XML node is being mapped
mutating func mapping(map: XMLMap)
This function is where all mapping definitions should go. When parsing XML, this function is executed after successful object creation. When generating XML, it is the only function that is called on the object.
Note: This protocol should not be implemented directly. XMLMappable
or XMLStaticMappable
should be used instead
XMLMappable
Protocol (sub protocol of XMLBaseMappable
)
init?(map: XMLMap)
This failable initializer is used by XMLMapper for object creation. It can be used by developers to validate XML prior to object serialization. Returning nil within the function will prevent the mapping from occuring. You can inspect the XML
stored within the XMLMap
object to do your validation:
XMLStaticMappable
Protocol (sub protocol of XMLBaseMappable
)
XMLStaticMappable
is an alternative to XMLMappable
. It provides developers with a static function that is used by XMLMapper for object initialization instead of init?(map: XMLMap)
.
static func objectForMapping(map: XMLMap) -> XMLBaseMappable?
XMLMapper uses this function to get objects to use for mapping. Developers should return an instance of an object that conforms to XMLBaseMappable
in this function. This function can also be used to:
- validate XML prior to object serialization
- provide an existing cached object to be used for mapping
- return an object of another type (which also conforms to
XMLBaseMappable
) to be used for mapping. For instance, you may inspect the XML to infer the type of object that should be used for mapping
If you need to implement XMLMapper in an extension, you will need to adopt this protocol instead of XMLMappable
.
How to use
To support mapping, a class or struct just needs to implement the XMLMappable
protocol:
XMLMapper uses the <-
operator to define how each property maps to and from XML:
XMLMapper can map classes or structs composed of the following types:
Int
Bool
Double
Float
String
RawRepresentable
(Enums)Array<Any>
Dictionary<String, Any>
Object<T: XMLBaseMappable>
Array<T: XMLBaseMappable>
Set<T: XMLBaseMappable>
Dictionary<String, T: XMLBaseMappable>
Dictionary<String, Array<T: XMLBaseMappable>>
- Optionals and Implicitly Unwrapped Optionals of all the above
Basic XML mapping
Convert easily an XML string to XMLMappable
:
Or an XMLMappable
object to XML string:
XMLMapper
class can also provide the same functionality:
Advanced mapping
Set nodeName
property of your class to change the element's name:
Map easily XML attributes using the attributes
property of the XMLMap
:
Map array of elements:
Create your own custom transform type by implementing the XMLTransformType
protocol:
and use it in mapping:
Map nested XML elements by separating names with a dot:
Note: Nested mapping is currently supported only:
- for elements that are composed of only innerText (like the above example) and
- for attributes
This means that in order to map the actual price of the food in the following XML:
You need to use an XMLMappable object instead of a Float
:
Because of currency
attribute existence. The same applies to the following XML:
You need to use an XMLMappable object like:
Because of currency
element existence.
Swift 4.2 and unordered XML elements
Starting from Swift 4.2, XML elements are highly likely to have different order each time you run your app. (This happens because they are represented by a Dictionary
)
For this, since version 1.5.2 of the XMLMapper you can map and change the order of the nodes that appear inside another node using nodesOrder
property of XMLMap
:
Note: If you want to change the ordering of the nodes, make sure that you include, in the nodesOrder
array, all the node names that you want to appear in the XML string
Map CDATA wrapped values
Since version 2.0.0 of XMLMapper, CDATA support has added. CDATA wrapped strings now are mapped as an Array<Data>
by default, instead of String
which was the case in the previous versions. That had as a side effect the disability to serialize CDATA wrapped values.
For example using the following code:
Your result was always:
In version 2.0.0 we introduce the build in XMLCDATATransform
type, which can be used like this:
and the result will be:
The breaking change here is that the deserialization of CDATA wrapped values cannot achieved, unless you use XMLCDATATransform
type. For example if you try to map the above XML to the following model class:
You will end up with nil
as the value of description
property.
Note: That default behaviour can be changed if you run xmlObject(withString:encoding:options:)
function of XMLSerialization
yourself and pass as options
the default
set, including cdataAsString
option.
For example, the following code will work:
XML Mapping example
map XML:
to classes:
Requests subspec
Note: Requests
subspec has different minimum deployment targets due to Alamofire
dependency. (currently iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+)
Create and send easily request with XML body using Alamofire
(added missing XMLEncoding
struct)
Also map XML responses to XMLMappable
objects using the Alamofire
extension. For example a URL returns the following CD catalog:
Map the response as follows:
The CDCatalog
object will look something like this:
Last but not least, create easily and send SOAP requests, again using Alamofire
:
The request will look something like this:
Adding action parameters is as easy as subclassing the SOAPMessage
class.
Also specify the SOAP version that the endpoint use as follows:
and the request will change to this:
Unfortunately, there isn't an easy way to map SOAP response, other than creating your own XMLMappable objects (at least not for the moment)
Communication
- If you need help, use Stack Overflow. (Tag 'xmlmapper')
- If you'd like to ask a general question, use Stack Overflow.
- If you found a bug, open an issue.
- If you have a feature request, open an issue.
Installation
CocoaPods
XMLMapper is available through CocoaPods. To install
it, simply add the following line to your Podfile
:
To install the Requests
subspec add the following line to your Podfile
:
Carthage
To integrate XMLMapper into your Xcode project using Carthage, add the following line to your Cartfile
:
Swift Package Manager
To add XMLMapper to a Swift Package Manager based project, add the following:
to the dependencies
value of your Package.swift
.
Special thanks
- Special thanks to Tristan Himmelman. This project is based in ObjectMapper for the most part, which is a great solution for JSON mapping. Also the Requests subspec is based on AlamofireObjectMapper.
- A special thanks to Nick Lockwood and his idea behind XMLDictionary
- A special thanks to Alamofire for the subspec dependency
License
XMLMapper is available under the MIT license. See the LICENSE file for more info.