{"id":15038029,"url":"https://github.com/coreoffice/xmlcoder","last_synced_at":"2026-04-02T02:07:36.517Z","repository":{"id":40547208,"uuid":"156681868","full_name":"CoreOffice/XMLCoder","owner":"CoreOffice","description":"Easy XML parsing using Codable protocols in Swift","archived":false,"fork":false,"pushed_at":"2024-02-12T11:28:37.000Z","size":1685,"stargazers_count":823,"open_issues_count":60,"forks_count":112,"subscribers_count":22,"default_branch":"main","last_synced_at":"2025-05-09T05:34:39.836Z","etag":null,"topics":["carthage","cocoapods","codable","decoder","encoder","swift","swift4","xml","xml-parser","xml-serializer"],"latest_commit_sha":null,"homepage":"https://swiftpackageindex.com/CoreOffice/XMLCoder","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CoreOffice.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"MaxDesiatov","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2018-11-08T09:26:06.000Z","updated_at":"2025-05-03T20:29:33.000Z","dependencies_parsed_at":"2024-01-07T22:23:34.714Z","dependency_job_id":"8ff4f0e7-0439-47fd-8ca6-d88afe3bca40","html_url":"https://github.com/CoreOffice/XMLCoder","commit_stats":{"total_commits":316,"total_committers":29,"mean_commits":10.89655172413793,"dds":0.4493670886075949,"last_synced_commit":"c10bb50cbfe1655808cd68fc0ed36142ba3b7504"},"previous_names":["maxdesiatov/xmlcoder"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoreOffice%2FXMLCoder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoreOffice%2FXMLCoder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoreOffice%2FXMLCoder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoreOffice%2FXMLCoder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CoreOffice","download_url":"https://codeload.github.com/CoreOffice/XMLCoder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254453655,"owners_count":22073617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carthage","cocoapods","codable","decoder","encoder","swift","swift4","xml","xml-parser","xml-serializer"],"created_at":"2024-09-24T20:36:51.887Z","updated_at":"2026-04-02T02:07:36.485Z","avatar_url":"https://github.com/CoreOffice.png","language":"Swift","readme":"# XMLCoder\n\nEncoder \u0026amp; Decoder for XML using Swift's `Codable` protocols.\n\n[![Version](https://img.shields.io/cocoapods/v/XMLCoder.svg?style=flat)](https://cocoapods.org/pods/XMLCoder)\n[![License](https://img.shields.io/cocoapods/l/XMLCoder.svg?style=flat)](https://cocoapods.org/pods/XMLCoder)\n[![Platform](https://img.shields.io/badge/platform-watchos%20%7C%20ios%20%7C%20tvos%20%7C%20macos%20%7C%20linux%20%7C%20windows-lightgrey.svg?style=flat)](https://cocoapods.org/pods/XMLCoder)\n[![Coverage](https://img.shields.io/codecov/c/github/CoreOffice/XMLCoder/main.svg?style=flat)](https://codecov.io/gh/maxdesiatov/XMLCoder)\n\nThis package is a fork of the original\n[ShawnMoore/XMLParsing](https://github.com/ShawnMoore/XMLParsing)\nwith more features and improved test coverage. Automatically generated documentation is available on [our GitHub Pages](https://coreoffice.github.io/XMLCoder/).\n\n[Join our Discord](https://discord.gg/H6799jh) for any questions and friendly banter.\n\n## Example\n\n```swift\nimport XMLCoder\nimport Foundation\n\nlet sourceXML = \"\"\"\n\u003cnote\u003e\n    \u003cto\u003eBob\u003c/to\u003e\n    \u003cfrom\u003eJane\u003c/from\u003e\n    \u003cheading\u003eReminder\u003c/heading\u003e\n    \u003cbody\u003eDon't forget to use XMLCoder!\u003c/body\u003e\n\u003c/note\u003e\n\"\"\"\n\nstruct Note: Codable {\n    let to: String\n    let from: String\n    let heading: String\n    let body: String\n}\n\nlet note = try! XMLDecoder().decode(Note.self, from: Data(sourceXML.utf8))\n\nlet encodedXML = try! XMLEncoder().encode(note, withRootKey: \"note\")\n```\n\n## Advanced features\n\nThe following features are available in [0.4.0\nrelease](https://github.com/CoreOffice/XMLCoder/releases/tag/0.4.0) or later\n(unless stated otherwise):\n\n### Stripping namespace prefix\n\nSometimes you need to handle an XML namespace prefix, like in the XML below:\n\n```xml\n\u003ch:table xmlns:h=\"http://www.w3.org/TR/html4/\"\u003e\n  \u003ch:tr\u003e\n    \u003ch:td\u003eApples\u003c/h:td\u003e\n    \u003ch:td\u003eBananas\u003c/h:td\u003e\n  \u003c/h:tr\u003e\n\u003c/h:table\u003e\n```\n\nStripping the prefix from element names is enabled with\n`shouldProcessNamespaces` property:\n\n```swift\nstruct Table: Codable, Equatable {\n    struct TR: Codable, Equatable {\n        let td: [String]\n    }\n\n    let tr: [TR]\n}\n\n\nlet decoder = XMLDecoder()\n\n// Setting this property to `true` for the namespace prefix to be stripped\n// during decoding so that key names could match.\ndecoder.shouldProcessNamespaces = true\n\nlet decoded = try decoder.decode(Table.self, from: xmlData)\n```\n\n### Dynamic node coding\n\nXMLCoder provides two helper protocols that allow you to customize whether nodes\nare encoded and decoded as attributes or elements: `DynamicNodeEncoding` and\n`DynamicNodeDecoding`.\n\nThe declarations of the protocols are very simple:\n\n```swift\nprotocol DynamicNodeEncoding: Encodable {\n    static func nodeEncoding(for key: CodingKey) -\u003e XMLEncoder.NodeEncoding\n}\n\nprotocol DynamicNodeDecoding: Decodable {\n    static func nodeDecoding(for key: CodingKey) -\u003e XMLDecoder.NodeDecoding\n}\n```\n\nThe values returned by corresponding `static` functions look like this:\n\n```swift\nenum NodeDecoding {\n    // decodes a value from an attribute\n    case attribute\n\n    // decodes a value from an element\n    case element\n\n    // the default, attempts to decode as an element first,\n    // otherwise reads from an attribute\n    case elementOrAttribute\n}\n\nenum NodeEncoding {\n    // encodes a value in an attribute\n    case attribute\n\n    // the default, encodes a value in an element\n    case element\n\n    // encodes a value in both attribute and element\n    case both\n}\n```\n\nAdd conformance to an appropriate protocol for types you'd like to customize.\nAccordingly, this example code:\n\n```swift\nstruct Book: Codable, Equatable, DynamicNodeEncoding {\n    let id: UInt\n    let title: String\n    let categories: [Category]\n\n    enum CodingKeys: String, CodingKey {\n        case id\n        case title\n        case categories = \"category\"\n    }\n\n    static func nodeEncoding(for key: CodingKey) -\u003e XMLEncoder.NodeEncoding {\n        switch key {\n        case Book.CodingKeys.id: return .both\n        default: return .element\n        }\n    }\n}\n```\n\nworks for this XML:\n\n```xml\n\u003cbook id=\"123\"\u003e\n    \u003cid\u003e123\u003c/id\u003e\n    \u003ctitle\u003eCat in the Hat\u003c/title\u003e\n    \u003ccategory\u003eKids\u003c/category\u003e\n    \u003ccategory\u003eWildlife\u003c/category\u003e\n\u003c/book\u003e\n```\n\nPlease refer to PR [\\#70](https://github.com/CoreOffice/XMLCoder/pull/70) by\n[@JoeMatt](https://github.com/JoeMatt) for more details.\n\n### Coding key value intrinsic\n\nSuppose that you need to decode an XML that looks similar to this:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cfoo id=\"123\"\u003e456\u003c/foo\u003e\n```\n\nBy default you'd be able to decode `foo` as an element, but then it's not\npossible to decode the `id` attribute. `XMLCoder` handles certain `CodingKey`\nvalues in a special way to allow proper coding for this XML. Just add a coding\nkey with `stringValue` that equals `\"\"` (empty string). What\nfollows is an example type declaration that encodes the XML above, but special\nhandling of coding keys with those values works for both encoding and decoding.\n\n```swift\nstruct Foo: Codable, DynamicNodeEncoding {\n    let id: String\n    let value: String\n\n    enum CodingKeys: String, CodingKey {\n        case id\n        case value = \"\"\n    }\n\n    static func nodeEncoding(forKey key: CodingKey)\n    -\u003e XMLEncoder.NodeEncoding {\n        switch key {\n        case CodingKeys.id:\n            return .attribute\n        default:\n            return .element\n        }\n    }\n}\n```\n\nThanks to [@JoeMatt](https://github.com/JoeMatt) for implementing this in\nin PR [\\#73](https://github.com/CoreOffice/XMLCoder/pull/73).\n\n### Preserving whitespaces in element content\n\nBy default whitespaces are trimmed in element content during decoding. This\nincludes string values decoded with [value intrinsic keys](#coding-key-value-intrinsic).\nStarting with [version 0.5](https://github.com/CoreOffice/XMLCoder/releases/tag/0.5.0)\nyou can now set a property `trimValueWhitespaces` to `false` (the default value is `true`) on\n`XMLDecoder` instance to preserve all whitespaces in decoded strings.\n\n### Remove whitespace elements\n\nWhen decoding pretty-printed XML while `trimValueWhitespaces` is set to `false`, it's possible\nfor whitespace elements to be added as child elements on an instance of `XMLCoderElement`. These\nwhitespace elements make it impossible to decode data structures that require custom `Decodable` logic.\nStarting with [version 0.13.0](https://github.com/CoreOffice/XMLCoder/releases/tag/0.13.0) you can\nset a property `removeWhitespaceElements` to `true` (the default value is `false`) on\n`XMLDecoder` to remove these whitespace elements.\n\n### Choice element coding\n\nStarting with [version 0.8](https://github.com/CoreOffice/XMLCoder/releases/tag/0.8.0),\nyou can encode and decode `enum`s with associated values by conforming your\n`CodingKey` type additionally to `XMLChoiceCodingKey`. This allows encoding \nand decoding XML elements similar in structure to this example:\n\n```xml\n\u003ccontainer\u003e\n    \u003cint\u003e1\u003c/int\u003e\n    \u003cstring\u003etwo\u003c/string\u003e\n    \u003cstring\u003ethree\u003c/string\u003e\n    \u003cint\u003e4\u003c/int\u003e\n    \u003cint\u003e5\u003c/int\u003e\n\u003c/container\u003e\n```\n\nTo decode these elements you can use this type:\n\n```swift\nenum IntOrString: Codable {\n    case int(Int)\n    case string(String)\n    \n    enum CodingKeys: String, XMLChoiceCodingKey {\n        case int\n        case string\n    }\n    \n    enum IntCodingKeys: String, CodingKey { case _0 = \"\" }\n    enum StringCodingKeys: String, CodingKey { case _0 = \"\" }\n}\n```\n\nThis is described in more details in PR [\\#119](https://github.com/CoreOffice/XMLCoder/pull/119)\nby [@jsbean](https://github.com/jsbean) and [@bwetherfield](https://github.com/bwetherfield).\n\n#### Choice elements with (inlined) complex associated values\n\nLets extend previous example replacing simple types with complex \nin assosiated values. This example would cover XML like:\n\n```xml\n\u003ccontainer\u003e\n    \u003cnested attr=\"n1_a1\"\u003e\n        \u003cval\u003en1_v1\u003c/val\u003e\n        \u003clabeled\u003e\n            \u003cval\u003en2_val\u003c/val\u003e\n        \u003c/labeled\u003e\n    \u003c/nested\u003e\n    \u003csimple attr=\"n1_a1\"\u003e\n        \u003cval\u003en1_v1\u003c/val\u003e\n    \u003c/simple\u003e\n\u003c/container\u003e\n```\n\n```swift\nenum InlineChoice: Equatable, Codable {\n    case simple(Nested1)\n    case nested(Nested1, labeled: Nested2)\n    \n    enum CodingKeys: String, CodingKey, XMLChoiceCodingKey {\n        case simple, nested\n    }\n    \n    enum SimpleCodingKeys: String, CodingKey { case _0 = \"\" }\n    \n    enum NestedCodingKeys: String, CodingKey {\n        case _0 = \"\"\n        case labeled\n    }\n    \n    struct Nested1: Equatable, Codable, DynamicNodeEncoding {\n        var attr = \"n1_a1\"\n        var val = \"n1_v1\"\n        \n        public static func nodeEncoding(for key: CodingKey) -\u003e XMLEncoder.NodeEncoding {\n            switch key {\n            case CodingKeys.attr: return .attribute\n            default: return .element\n            }\n        }\n    }\n\n    struct Nested2: Equatable, Codable {\n        var val = \"n2_val\"\n    }\n}\n```\n\n### Integrating with [Combine](https://developer.apple.com/documentation/combine)\n\nStarting with XMLCoder [version 0.9](https://github.com/CoreOffice/XMLCoder/releases/tag/0.9.0),\nwhen Apple's Combine framework is available, `XMLDecoder` conforms to the\n`TopLevelDecoder` protocol, which allows it to be used with the\n`decode(type:decoder:)` operator:\n\n```swift\nimport Combine\nimport Foundation\nimport XMLCoder\n\nfunc fetchBook(from url: URL) -\u003e AnyPublisher\u003cBook, Error\u003e {\n    return URLSession.shared.dataTaskPublisher(for: url)\n        .map(\\.data)\n        .decode(type: Book.self, decoder: XMLDecoder())\n        .eraseToAnyPublisher()\n}\n```\n\nThis was implemented in PR [\\#132](https://github.com/CoreOffice/XMLCoder/pull/132)\nby [@sharplet](https://github.com/sharplet).\n\nAdditionally, starting with [XMLCoder\n0.11](https://github.com/CoreOffice/XMLCoder/releases/tag/0.11.0) `XMLEncoder`\nconforms to the `TopLevelEncoder` protocol:\n\n```swift\nimport Combine\nimport XMLCoder\n\nfunc encode(book: Book) -\u003e AnyPublisher\u003cData, Error\u003e {\n    return Just(book)\n        .encode(encoder: XMLEncoder())\n        .eraseToAnyPublisher()\n}\n```\n\nThe resulting XML in the example above will start with `\u003cbook`, to customize\ncapitalization of the root element (e.g. `\u003cBook`) you'll need to set an\nappropriate `keyEncoding` strategy on the encoder. To change the element name\naltogether you'll have to change the name of the type, which is an unfortunate\nlimitation of the `TopLevelEncoder` API.\n\n### Root element attributes\n\nSometimes you need to set attributes on the root element, which aren't\ndirectly related to your model type. Starting with [XMLCoder\n0.11](https://github.com/CoreOffice/XMLCoder/releases/tag/0.11.0) the `encode`\nfunction on `XMLEncoder` accepts a new `rootAttributes` argument to help with\nthis:\n\n```swift\nstruct Policy: Encodable {\n    var name: String\n}\n\nlet encoder = XMLEncoder()\nlet data = try encoder.encode(Policy(name: \"test\"), rootAttributes: [\n    \"xmlns\": \"http://www.nrf-arts.org/IXRetail/namespace\",\n    \"xmlns:xsd\": \"http://www.w3.org/2001/XMLSchema\",\n    \"xmlns:xsi\": \"http://www.w3.org/2001/XMLSchema-instance\",\n])\n```\n\nThe resulting XML will look like this:\n\n```xml\n\u003cpolicy xmlns=\"http://www.nrf-arts.org/IXRetail/namespace\"\n        xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\u003e\n    \u003cname\u003etest\u003c/name\u003e\n\u003c/policy\u003e\n```\n\nThis was implemented in PR [\\#160](https://github.com/CoreOffice/XMLCoder/pull/160)\nby [@portellaa](https://github.com/portellaa).\n\n### Property wrappers\n\nIf your version of Swift allows property wrappers to be used, you may prefer this API to the more verbose\n[dynamic node coding](#dynamic-node-coding). \n\nFor example, this type\n```swift\nstruct Book: Codable {\n    @Element var id: Int\n}\n```\n\nwill encode value `Book(id: 42)` as `\u003cBook\u003e\u003cid\u003e42\u003c/id\u003e\u003c/Book\u003e`. And vice versa,\nit will decode the latter into the former.\n\nSimilarly,\n \n```swift\nstruct Book: Codable {\n    @Attribute var id: Int\n}\n```\n\nwill encode value `Book(id: 42)` as `\u003cBook id=\"42\"\u003e\u003c/Book\u003e` and vice versa for decoding.\n \nIf you don't know upfront if a property will be present as an element or an attribute during decoding,\nuse `@ElementAndAttribute`:\n\n```swift\nstruct Book: Codable {\n    @ElementAndAttribute var id: Int\n}\n```\n\nThis will encode value `Book(id: 42)` as `\u003cBook id=\"42\"\u003e\u003cid\u003e42\u003c/id\u003e\u003c/Book\u003e`. It will decode both\n`\u003cBook\u003e\u003cid\u003e42\u003c/id\u003e\u003c/Book\u003e` and `\u003cBook id=\"42\"\u003e\u003c/Book\u003e` as `Book(id: 42)`.\n\nThis feature is available starting with XMLCoder 0.13.0 and was implemented\nby [@bwetherfield](https://github.com/bwetherfield).\n\n### XML Headers\n\nYou can add an XML header and/or doctype when encoding an object by supplying it to the `encode` function.\nThese arguments are both optional, and will only render when explicitly provided.\n\n```swift\nstruct User: Codable {\n    @Element var username: String\n}\n\nlet data = try encoder.encode(\n    User(username: \"Joanis\"),\n    withRootKey: \"user\",\n    header: XMLHeader(version: 1.0, encoding: \"UTF-8\"),\n    doctype: .system(\n        rootElement: \"user\",\n        dtdLocation: \"http://example.com/myUser_v1.dtd\"\n    )\n)\n```\n\n## Installation\n\n### Requirements\n\n**Apple Platforms**\n\n- Xcode 11.0 or later\n  - **IMPORTANT**: compiling XMLCoder with Xcode 11.2.0 (11B52) and 11.2.1 (11B500) is not recommended due to crashes with `EXC_BAD_ACCESS` caused by [a compiler bug](https://bugs.swift.org/browse/SR-11564), please use Xcode 11.3 or later instead. Please refer to [\\#150](https://github.com/CoreOffice/XMLCoder/issues/150) for more details.\n- Swift 5.1 or later\n- iOS 9.0 / watchOS 2.0 / tvOS 9.0 / macOS 10.10 or later deployment targets\n\n**Linux**\n\n- Ubuntu 18.04 or later\n- Swift 5.1 or later\n\n**Windows**\n\n- Swift 5.5 or later.\n\n### Swift Package Manager\n\n[Swift Package Manager](https://swift.org/package-manager/) is a tool for\nmanaging the distribution of Swift code. It’s integrated with the Swift build\nsystem to automate the process of downloading, compiling, and linking\ndependencies on all platforms.\n\nOnce you have your Swift package set up, adding `XMLCoder` as a dependency is as\neasy as adding it to the `dependencies` value of your `Package.swift`.\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/CoreOffice/XMLCoder.git\", from: \"0.15.0\")\n]\n```\n\nIf you're using XMLCoder in an app built with Xcode, you can also add it as a direct\ndependency [using Xcode's\nGUI](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app).\n\n### CocoaPods\n\n[CocoaPods](https://cocoapods.org) is a dependency manager for Swift and Objective-C\nCocoa projects for Apple's platfoms. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\nNavigate to the project directory and create `Podfile` with the following command:\n\n```bash\n$ pod install\n```\n\nInside of your `Podfile`, specify the `XMLCoder` pod:\n\n```ruby\n# Uncomment the next line to define a global platform for your project\n# platform :ios, '9.0'\n\ntarget 'YourApp' do\n  # Comment the next line if you're not using Swift or don't want\n  # to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for YourApp\n  pod 'XMLCoder', '~\u003e 0.14.0'\nend\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\nOpen the the `YourApp.xcworkspace` file that was created. This should be the\nfile you use everyday to create your app, instead of the `YourApp.xcodeproj`\nfile.\n\n### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a dependency manager for Apple's\nplatfoms that builds your dependencies and provides you with binary frameworks.\n\nCarthage can be installed with [Homebrew](https://brew.sh/) using the following command:\n\n```bash\n$ brew update\n$ brew install carthage\n```\n\nInside of your `Cartfile`, add GitHub path to `XMLCoder`:\n\n```ogdl\ngithub \"CoreOffice/XMLCoder\" ~\u003e 0.15.0\n```\n\nThen, run the following command to build the framework:\n\n```bash\n$ carthage update\n```\n\nDrag the built framework into your Xcode project.\n\n## Usage with Vapor\n\n```swift\nextension XMLEncoder: ContentEncoder {\n    public func encode\u003cE: Encodable\u003e(\n        _ encodable: E,\n        to body: inout ByteBuffer,\n        headers: inout HTTPHeaders\n    ) throws {\n        headers.contentType = .xml\n        \n        // Note: You can provide an XMLHeader or DocType if necessary\n        let data = try self.encode(encodable)\n        body.writeData(data)\n    }\n}\n\nextension XMLDecoder: ContentDecoder {\n    public func decode\u003cD: Decodable\u003e(\n        _ decodable: D.Type,\n        from body: ByteBuffer,\n        headers: HTTPHeaders\n    ) throws -\u003e D {\n        // Force wrap is acceptable, as we're guaranteed these bytes exist through `readableBytes`\n        let body = body.readData(length: body.readableBytes)!\n        return try self.decode(D.self, from: body)\n    }\n}\n```\n\n## Contributing\n\nThis project adheres to the [Contributor Covenant Code of\nConduct](https://github.com/CoreOffice/XMLCoder/blob/main/CODE_OF_CONDUCT.md).\nBy participating, you are expected to uphold this code. Please report\nunacceptable behavior to coreoffice@desiatov.com.\n\n### Coding Style\n\nThis project uses [SwiftFormat](https://github.com/nicklockwood/SwiftFormat)\nand [SwiftLint](https://github.com/realm/SwiftLint) to\nenforce formatting and coding style. We encourage you to run SwiftFormat within\na local clone of the repository in whatever way works best for you either\nmanually or automatically via an [Xcode\nextension](https://github.com/nicklockwood/SwiftFormat#xcode-source-editor-extension),\n[build phase](https://github.com/nicklockwood/SwiftFormat#xcode-build-phase) or\n[git pre-commit\nhook](https://github.com/nicklockwood/SwiftFormat#git-pre-commit-hook) etc.\n\nTo guarantee that these tools run before you commit your changes on macOS, you're encouraged\nto run this once to set up the [pre-commit](https://pre-commit.com/) hook:\n\n```\nbrew bundle # installs SwiftLint, SwiftFormat and pre-commit\npre-commit install # installs pre-commit hook to run checks before you commit\n```\n\nRefer to [the pre-commit documentation page](https://pre-commit.com/) for more details\nand installation instructions for other platforms.\n\nSwiftFormat and SwiftLint also run on CI for every PR and thus a CI build can\nfail with incosistent formatting or style. We require CI builds to pass for all\nPRs before merging.\n\n### Test Coverage\n\nOur goal is to keep XMLCoder stable and to serialize any XML correctly according\nto [XML 1.0 standard](https://www.w3.org/TR/2008/REC-xml-20081126/). All of this\ncan be easily tested automatically and we're slowly improving [test coverage of\nXMLCoder](https://codecov.io/gh/CoreOffice/XMLCoder) and don't expect it to\ndecrease. PRs that decrease the test coverage have a much lower chance of being\nmerged. If you add any new features, please make sure to add tests, likewise for\nchanges and any refactoring in existing code.\n","funding_links":["https://github.com/sponsors/MaxDesiatov"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreoffice%2Fxmlcoder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoreoffice%2Fxmlcoder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreoffice%2Fxmlcoder/lists"}