{"id":1748,"url":"https://github.com/drmohundro/SWXMLHash","last_synced_at":"2025-08-06T13:32:26.920Z","repository":{"id":717561,"uuid":"21636933","full_name":"drmohundro/SWXMLHash","owner":"drmohundro","description":"Simple XML parsing in Swift","archived":false,"fork":false,"pushed_at":"2024-09-27T19:58:10.000Z","size":1008,"stargazers_count":1406,"open_issues_count":1,"forks_count":205,"subscribers_count":34,"default_branch":"main","last_synced_at":"2024-10-29T15:33:08.127Z","etag":null,"topics":["swift","swxmlhash","xml-parsing"],"latest_commit_sha":null,"homepage":null,"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/drmohundro.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-07-09T02:53:38.000Z","updated_at":"2024-10-22T13:11:49.000Z","dependencies_parsed_at":"2024-06-18T11:10:21.700Z","dependency_job_id":"5aa5594d-843d-4de8-93a2-f40736e8222f","html_url":"https://github.com/drmohundro/SWXMLHash","commit_stats":{"total_commits":429,"total_committers":47,"mean_commits":9.127659574468085,"dds":0.3613053613053613,"last_synced_commit":"eacfa68203c7595f7988e36a037a0decfc74dc33"},"previous_names":[],"tags_count":70,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drmohundro%2FSWXMLHash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drmohundro%2FSWXMLHash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drmohundro%2FSWXMLHash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drmohundro%2FSWXMLHash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drmohundro","download_url":"https://codeload.github.com/drmohundro/SWXMLHash/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222100819,"owners_count":16931669,"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":["swift","swxmlhash","xml-parsing"],"created_at":"2024-01-05T20:15:54.848Z","updated_at":"2024-12-09T14:30:51.840Z","avatar_url":"https://github.com/drmohundro.png","language":"Swift","funding_links":[],"categories":["Parsing","Libs","Swift","JSON/XML Manipulation","Data Management [🔝](#readme)","Processing Libraries"],"sub_categories":["XML \u0026 HTML","Data Management","Other free courses","Libraries"],"readme":"# SWXMLHash\n\n[![Swift](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdrmohundro%2FSWXMLHash%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/drmohundro/SWXMLHash)\n[![Platforms](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdrmohundro%2FSWXMLHash%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/drmohundro/SWXMLHash)\n[![Swift Package Manager](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/SWXMLHash)](https://cocoapods.org/pods/SWXMLHash)\n[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n\nSWXMLHash is a relatively simple way to parse XML in Swift. If you're familiar\nwith `XMLParser` (formerly `NSXMLParser`), this library is a wrapper around it. Conceptually, it\nprovides a translation from XML to a dictionary of arrays (aka hash).\n\nThe API takes a lot of inspiration from\n[SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON).\n\n## Contents\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n- [Configuration](#configuration)\n- [Examples](#examples)\n- [FAQ](#faq)\n- [Changelog](#changelog)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Requirements\n\n- iOS 8.0+ / Mac OS X 10.9+ / tvOS 9.0+ / watchOS 2.0+\n- Xcode 8.0+\n\n## Installation\n\nSWXMLHash can be installed using [Swift Package Manager](https://swift.org/package-manager/), [CocoaPods](http://cocoapods.org/),\n[Carthage](https://github.com/Carthage/Carthage), or manually.\n\n### Swift Package Manager\n\nThe [Swift Package Manager](https://swift.org/package-manager/) is a tool built by Apple as part of [the Swift project](https://swift.org/) for integrating libraries and frameworks into your Swift apps.\n\nTo add SWXMLHash as a dependency, update the `dependencies` in your `Package.swift` to include a reference like so:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/drmohundro/SWXMLHash.git\", from: \"7.0.0\")\n]\n```\n\n`swift build` should then pull in and compile SWXMLHash to begin using.\n\n### CocoaPods\n\nTo install CocoaPods, run:\n\n```bash\ngem install cocoapods\n```\n\nThen create a `Podfile` with the following contents:\n\n```ruby\nplatform :ios, '10.0'\nuse_frameworks!\n\ntarget 'YOUR_TARGET_NAME' do\n  pod 'SWXMLHash', '~\u003e 7.0.0'\nend\n```\n\nFinally, run the following command to install it:\n\n```bash\npod install\n```\n\n### Carthage\n\nTo install Carthage, run (using Homebrew):\n\n```bash\nbrew update\nbrew install carthage\n```\n\nThen add the following line to your `Cartfile`:\n\n```\ngithub \"drmohundro/SWXMLHash\" ~\u003e 7.0\n```\n\n### Manual Installation\n\nTo install manually, you'll need to clone the SWXMLHash repository. You can do\nthis in a separate directory, or you can make use of git submodules - in this\ncase, git submodules are recommended so that your repository has details about\nwhich commit of SWXMLHash you're using. Once this is done, you can just drop all\nof the relevant swift files into your project.\n\nIf you're using a workspace, though, you can include the entire `SWXMLHash.xcodeproj`.\n\n## Getting Started\n\nIf you're just getting started with SWXMLHash, I'd recommend cloning the\nrepository down and opening the workspace. I've included a Swift playground in\nthe workspace which makes it easy to experiment with the API and the calls.\n\n![Swift Playground](https://raw.githubusercontent.com/drmohundro/SWXMLHash/assets/swift-playground@2x.png)\n\n## Configuration\n\nSWXMLHash allows for limited configuration in terms of its approach to parsing.\nTo set any of the configuration options, you use the `configure` method, like\nso:\n\n```swift\nlet xml = XMLHash.config {\n              config in\n              // set any config options here\n          }.parse(xmlToParse)\n```\n\nThe available options at this time are:\n\n- `shouldProcessLazily`\n  - This determines whether not to use lazy loading of the XML. It can\n    significantly increase the performance of parsing if your XML is large.\n  - Defaults to `false`\n- `shouldProcessNamespaces`\n  - This setting is forwarded on to the internal `NSXMLParser` instance. It will\n    return any XML elements without their namespace parts (i.e. \"\\\u003ch:table\\\u003e\"\n    will be returned as \"\\\u003ctable\\\u003e\")\n  - Defaults to `false`\n- `caseInsensitive`\n  - This setting allows for key lookups to be case-insensitive. Typically, XML is\n    a case-sensitive language, but this option lets you bypass this if\n    necessary.\n  - Defaults to `false`\n- `encoding`\n  - This setting allows for explicitly specifying the character encoding when an\n    XML string is passed to `parse`.\n  - Defaults to `String.encoding.utf8`\n- `userInfo`\n  - This setting mimics `Codable`'s `userInfo` property to allow the user to add\n    contextual information that will be used for deserialization.\n  - See\n    [Codable's userInfo docs](https://developer.apple.com/documentation/swift/encoder/2894907-userinfo)\n  - The default is [:]\n- `detectParsingErrors`\n  - This setting attempts to detect XML parsing errors. `parse` will return an\n    `XMLIndexer.parsingError` if any parsing issues are found.\n  - Defaults to `false` (because of backwards compatibility and because many\n    users attempt to parse HTML with this library)\n\n## Examples\n\nAll examples below can be found in the included\n[specs](https://github.com/drmohundro/SWXMLHash/blob/main/Tests/).\n\n### Initialization\n\n```swift\nlet xml = XMLHash.parse(xmlToParse)\n```\n\nAlternatively, if you're parsing a large XML file and need the best performance,\nyou may wish to configure the parsing to be processed lazily. Lazy processing\navoids loading the entire XML document into memory, so it could be preferable\nfor performance reasons. See the error handling for one caveat regarding lazy\nloading.\n\n```swift\nlet xml = XMLHash.config {\n              config in\n              config.shouldProcessLazily = true\n          }.parse(xmlToParse)\n```\n\nThe above approach uses the config method, but there is also a `lazy` method\ndirectly off of `XMLHash`.\n\n```swift\nlet xml = XMLHash.lazy(xmlToParse)\n```\n\n### Single Element Lookup\n\nGiven:\n\n```xml\n\u003croot\u003e\n  \u003cheader\u003e\n    \u003ctitle\u003eFoo\u003c/title\u003e\n  \u003c/header\u003e\n  ...\n\u003c/root\u003e\n```\n\nWill return \"Foo\".\n\n```swift\nxml[\"root\"][\"header\"][\"title\"].element?.text\n```\n\n### Multiple Elements Lookup\n\nGiven:\n\n```xml\n\u003croot\u003e\n  ...\n  \u003ccatalog\u003e\n    \u003cbook\u003e\u003cauthor\u003eBob\u003c/author\u003e\u003c/book\u003e\n    \u003cbook\u003e\u003cauthor\u003eJohn\u003c/author\u003e\u003c/book\u003e\n    \u003cbook\u003e\u003cauthor\u003eMark\u003c/author\u003e\u003c/book\u003e\n  \u003c/catalog\u003e\n  ...\n\u003c/root\u003e\n```\n\nThe below will return \"John\".\n\n```swift\nxml[\"root\"][\"catalog\"][\"book\"][1][\"author\"].element?.text\n```\n\n### Attributes Usage\n\nGiven:\n\n```xml\n\u003croot\u003e\n  ...\n  \u003ccatalog\u003e\n    \u003cbook id=\"1\"\u003e\u003cauthor\u003eBob\u003c/author\u003e\u003c/book\u003e\n    \u003cbook id=\"123\"\u003e\u003cauthor\u003eJohn\u003c/author\u003e\u003c/book\u003e\n    \u003cbook id=\"456\"\u003e\u003cauthor\u003eMark\u003c/author\u003e\u003c/book\u003e\n  \u003c/catalog\u003e\n  ...\n\u003c/root\u003e\n```\n\nThe below will return \"123\".\n\n```swift\nxml[\"root\"][\"catalog\"][\"book\"][1].element?.attribute(by: \"id\")?.text\n```\n\nAlternatively, you can look up an element with specific attributes. The below\nwill return \"John\".\n\n```swift\nxml[\"root\"][\"catalog\"][\"book\"].withAttribute(\"id\", \"123\")[\"author\"].element?.text\n```\n\n### Returning All Elements At Current Level\n\nGiven:\n\n```xml\n\u003croot\u003e\n  ...\n  \u003ccatalog\u003e\n    \u003cbook\u003e\u003cgenre\u003eFiction\u003c/genre\u003e\u003c/book\u003e\n    \u003cbook\u003e\u003cgenre\u003eNon-fiction\u003c/genre\u003e\u003c/book\u003e\n    \u003cbook\u003e\u003cgenre\u003eTechnical\u003c/genre\u003e\u003c/book\u003e\n  \u003c/catalog\u003e\n  ...\n\u003c/root\u003e\n```\n\nThe `all` method will iterate over all nodes at the indexed level. The code\nbelow will return \"Fiction, Non-fiction, Technical\".\n\n```swift\n\", \".join(xml[\"root\"][\"catalog\"][\"book\"].all.map { elem in\n    elem[\"genre\"].element!.text!\n})\n```\n\nYou can also iterate over the `all` method:\n\n```swift\nfor elem in xml[\"root\"][\"catalog\"][\"book\"].all {\n    print(elem[\"genre\"].element!.text!)\n}\n```\n\n### Returning All Child Elements At Current Level\n\nGiven:\n\n```xml\n\u003croot\u003e\n  \u003ccatalog\u003e\n    \u003cbook\u003e\n      \u003cgenre\u003eFiction\u003c/genre\u003e\n      \u003ctitle\u003eBook\u003c/title\u003e\n      \u003cdate\u003e1/1/2015\u003c/date\u003e\n    \u003c/book\u003e\n  \u003c/catalog\u003e\n\u003c/root\u003e\n```\n\nThe below will `print` \"root\", \"catalog\", \"book\", \"genre\", \"title\", and \"date\"\n(note the `children` method).\n\n```swift\nfunc enumerate(indexer: XMLIndexer) {\n    for child in indexer.children {\n        print(child.element!.name)\n        enumerate(child)\n    }\n}\n\nenumerate(indexer: xml)\n```\n\n### Filtering elements\n\nGiven:\n\n```xml\n\u003croot\u003e\n  \u003ccatalog\u003e\n    \u003cbook id=\"bk101\"\u003e\n      \u003cauthor\u003eGambardella, Matthew\u003c/author\u003e\n      \u003ctitle\u003eXML Developer's Guide\u003c/title\u003e\n      \u003cgenre\u003eComputer\u003c/genre\u003e\u003cprice\u003e44.95\u003c/price\u003e\n      \u003cpublish_date\u003e2000-10-01\u003c/publish_date\u003e\n    \u003c/book\u003e\n    \u003cbook id=\"bk102\"\u003e\n      \u003cauthor\u003eRalls, Kim\u003c/author\u003e\n      \u003ctitle\u003eMidnight Rain\u003c/title\u003e\n      \u003cgenre\u003eFantasy\u003c/genre\u003e\n      \u003cprice\u003e5.95\u003c/price\u003e\n      \u003cpublish_date\u003e2000-12-16\u003c/publish_date\u003e\n    \u003c/book\u003e\n    \u003cbook id=\"bk103\"\u003e\n      \u003cauthor\u003eCorets, Eva\u003c/author\u003e\n      \u003ctitle\u003eMaeve Ascendant\u003c/title\u003e\n      \u003cgenre\u003eFantasy\u003c/genre\u003e\n      \u003cprice\u003e5.95\u003c/price\u003e\n      \u003cpublish_date\u003e2000-11-17\u003c/publish_date\u003e\n    \u003c/book\u003e\n  \u003c/catalog\u003e\n\u003c/root\u003e\n```\n\nThe following will return \"Midnight Rain\". Filtering can be by any part\nof the `XMLElement` class or by index as well.\n\n```swift\nlet subIndexer = xml![\"root\"][\"catalog\"][\"book\"]\n    .filterAll { elem, _ in elem.attribute(by: \"id\")!.text == \"bk102\" }\n    .filterChildren { _, index in index \u003e= 1 \u0026\u0026 index \u003c= 3 }\n\nprint(subIndexer.children[0].element?.text)\n```\n\n### Error Handling\n\nUsing Do-Catch with Errors:\n\n```swift\ndo {\n    try xml!.byKey(\"root\").byKey(\"what\").byKey(\"header\").byKey(\"foo\")\n} catch let error as IndexingError {\n    // error is an IndexingError instance that you can deal with\n}\n```\n\n**Or** using the existing indexing functionality:\n\n```swift\nswitch xml[\"root\"][\"what\"][\"header\"][\"foo\"] {\ncase .element(let elem):\n    // everything is good, code away!\ncase .xmlError(let error):\n    // error is an IndexingError instance that you can deal with\n}\n```\n\nNote that error handling as shown above will not work with lazy loaded XML. The\nlazy parsing doesn't actually occur until the `element` or `all` method are\ncalled - as a result, there isn't any way to know prior to asking for an element\nif it exists or not.\n\n### XML Deserialization Into Objects\n\nEven more often, you'll want to deserialize an XML tree into an\narray of custom types. This is where `XMLObjectDeserialization`\ncomes into play.\n\nGiven:\n\n```xml\n\u003croot\u003e\n  \u003cbooks\u003e\n    \u003cbook isbn=\"0000000001\"\u003e\n      \u003ctitle\u003eBook A\u003c/title\u003e\n      \u003cprice\u003e12.5\u003c/price\u003e\n      \u003cyear\u003e2015\u003c/year\u003e\n      \u003ccategories\u003e\n        \u003ccategory\u003eC1\u003c/category\u003e\n        \u003ccategory\u003eC2\u003c/category\u003e\n      \u003c/categories\u003e\n    \u003c/book\u003e\n    \u003cbook isbn=\"0000000002\"\u003e\n      \u003ctitle\u003eBook B\u003c/title\u003e\n      \u003cprice\u003e10\u003c/price\u003e\n      \u003cyear\u003e1988\u003c/year\u003e\n      \u003ccategories\u003e\n        \u003ccategory\u003eC2\u003c/category\u003e\n        \u003ccategory\u003eC3\u003c/category\u003e\n      \u003c/categories\u003e\n    \u003c/book\u003e\n    \u003cbook isbn=\"0000000003\"\u003e\n      \u003ctitle\u003eBook C\u003c/title\u003e\n      \u003cprice\u003e8.33\u003c/price\u003e\n      \u003cyear\u003e1990\u003c/year\u003e\n      \u003camount\u003e10\u003c/amount\u003e\n      \u003ccategories\u003e\n        \u003ccategory\u003eC1\u003c/category\u003e\n        \u003ccategory\u003eC3\u003c/category\u003e\n      \u003c/categories\u003e\n    \u003c/book\u003e\n  \u003c/books\u003e\n\u003c/root\u003e\n```\n\nwith `Book` struct implementing `XMLObjectDeserialization`:\n\n```swift\nstruct Book: XMLObjectDeserialization {\n    let title: String\n    let price: Double\n    let year: Int\n    let amount: Int?\n    let isbn: Int\n    let category: [String]\n\n    static func deserialize(_ node: XMLIndexer) throws -\u003e Book {\n        return try Book(\n            title: node[\"title\"].value(),\n            price: node[\"price\"].value(),\n            year: node[\"year\"].value(),\n            amount: node[\"amount\"].value(),\n            isbn: node.value(ofAttribute: \"isbn\"),\n            category : node[\"categories\"][\"category\"].value()\n        )\n    }\n}\n```\n\nThe below will return an array of `Book` structs:\n\n```swift\nlet books: [Book] = try xml[\"root\"][\"books\"][\"book\"].value()\n```\n\n![Types Conversion](https://raw.githubusercontent.com/ncreated/SWXMLHash/assets/types-conversion%402x.png)\n\nYou can convert any XML to your custom type by implementing\n`XMLObjectDeserialization` for any non-leaf node (e.g. `\u003cbook\u003e` in the example\nabove).\n\nFor leaf nodes (e.g. `\u003ctitle\u003e` in the example above), built-in converters\nsupport `Int`, `Double`, `Float`, `Bool`, and `String` values (both non- and\n-optional variants). Custom converters can be added by implementing\n`XMLElementDeserializable`.\n\nFor attributes (e.g. `isbn=` in the example above), built-in converters support\nthe same types as above, and additional converters can be added by implementing\n`XMLAttributeDeserializable`.\n\nTypes conversion supports error handling, optionals and arrays. For more\nexamples, look into `SWXMLHashTests.swift` or play with types conversion\ndirectly in the Swift playground.\n\n### Custom Value Conversion\n\nValue deserialization is where a specific string value needs to be deserialized\ninto a custom type. So, date is a good example here - you'd rather deal with\ndate types than doing string parsing, right? That's what the `XMLValueDeserialization`\nattribute is for.\n\nGiven:\n\n```xml\n\u003croot\u003e\n  \u003celem\u003eMonday, 23 January 2016 12:01:12 111\u003c/elem\u003e\n\u003c/root\u003e\n```\n\nWith the following implementation for `Date` value deserialization:\n\n```swift\nextension Date: XMLValueDeserialization {\n    public static func deserialize(_ element: XMLHash.XMLElement) throws -\u003e Date {\n        let date = stringToDate(element.text)\n\n        guard let validDate = date else {\n            throw XMLDeserializationError.typeConversionFailed(type: \"Date\", element: element)\n        }\n\n        return validDate\n    }\n\n    public static func deserialize(_ attribute: XMLAttribute) throws -\u003e Date {\n        let date = stringToDate(attribute.text)\n\n        guard let validDate = date else {\n            throw XMLDeserializationError.attributeDeserializationFailed(type: \"Date\", attribute: attribute)\n        }\n\n        return validDate\n    }\n\n    public func validate() throws {\n        // empty validate... only necessary for custom validation logic after parsing\n    }\n\n    private static func stringToDate(_ dateAsString: String) -\u003e Date? {\n        let dateFormatter = DateFormatter()\n        dateFormatter.dateFormat = \"EEEE, dd MMMM yyyy HH:mm:ss SSS\"\n        return dateFormatter.date(from: dateAsString)\n    }\n}\n```\n\nThe below will return a date value:\n\n```swift\nlet dt: Date = try xml[\"root\"][\"elem\"].value()\n```\n\n## FAQ\n\n### Does SWXMLHash handle URLs for me?\n\nNo - SWXMLHash only handles parsing of XML. If you have a URL that has XML\ncontent on it, I'd recommend using a library like\n[AlamoFire](https://github.com/Alamofire/Alamofire) to download the content into\na string and then parsing it.\n\n### Does SWXMLHash support writing XML content?\n\nNo, not at the moment - SWXMLHash only supports parsing XML (via indexing,\ndeserialization, etc.).\n\n### I'm getting an \"Ambiguous reference to member 'subscript'\" when I call `.value()`\n\n`.value()` is used for deserialization - you have to have something that\nimplements `XMLObjectDeserialization` (or `XMLElementDeserializable` if it is a\nsingle element versus a group of elements) and that can handle deserialization\nto the left-hand side of expression.\n\nFor example, given the following:\n\n```swift\nlet dateValue: Date = try! xml[\"root\"][\"date\"].value()\n```\n\nYou'll get an error because there isn't any built-in deserializer for `Date`.\nSee the above documentation on adding your own deserialization support. In this\ncase, you would create your own `XMLElementDeserializable` implementation for\n`Date`. See above for an example of how to add your own `Date` deserialization\nsupport.\n\n### I'm getting an `EXC_BAD_ACCESS (SIGSEGV)` when I call `parse()`\n\nChances are very good that your XML content has what is called a \"byte order\nmark\" or BOM. SWXMLHash uses `NSXMLParser` for its parsing logic and there are\nissues with it and handling BOM characters. See\n[issue #65](https://github.com/drmohundro/SWXMLHash/issues/65) for more details.\nOthers who have run into this problem have just stripped the BOM out of their\ncontent prior to parsing.\n\n### How do I handle deserialization with a class versus a struct (such as with `NSDate`)?\n\nUsing extensions on classes instead of structs can result in some odd catches\nthat might give you a little trouble. For example, see\n[this question on StackOverflow](http://stackoverflow.com/questions/38174669/how-to-deserialize-nsdate-with-swxmlhash)\nwhere someone was trying to write their own `XMLElementDeserializable` for\n`NSDate` which is a class and not a struct. The `XMLElementDeserializable`\nprotocol expects a method that returns `Self` - this is the part that gets a\nlittle odd.\n\nSee below for the code snippet to get this to work and note in particular the\n`private static func value\u003cT\u003e() -\u003e T` line - that is the key.\n\n```swift\nextension NSDate: XMLElementDeserializable {\n    public static func deserialize(_ element: XMLElement) throws -\u003e Self {\n        guard let dateAsString = element.text else {\n            throw XMLDeserializationError.nodeHasNoValue\n        }\n\n        let dateFormatter = NSDateFormatter()\n        dateFormatter.dateFormat = \"EEE, dd MMM yyyy HH:mm:ss zzz\"\n        let date = dateFormatter.dateFromString(dateAsString)\n\n        guard let validDate = date else {\n            throw XMLDeserializationError.typeConversionFailed(type: \"Date\", element: element)\n        }\n\n        // NOTE THIS\n        return value(validDate)\n    }\n\n    // AND THIS\n    private static func value\u003cT\u003e(date: NSDate) -\u003e T {\n        return date as! T\n    }\n}\n```\n\n### How do I handle deserialization with an enum?\n\nCheck out this great suggestion/example from @woolie up at \u003chttps://github.com/drmohundro/SWXMLHash/discussions/245\u003e.\n\n### I'm seeing an \"\"'XMLElement' is ambiguous\" Error\n\nThis is related to \u003chttps://github.com/drmohundro/SWXMLHash/issues/256\u003e - `XMLElement` has actually been renamed\nmultiple times to attempt to avoid conflicts, but the easiest approach is to just scope it via `XMLHash.XMLElement`.\n\n### Will SWXMLHash work in a web context (e.g. Vapor)?\n\nSee \u003chttps://github.com/drmohundro/SWXMLHash/discussions/264\u003e where this is discussed. The only change needed is to\nadd the following import logic:\n\n```swift\n#if canImport(FoundationNetworking)\nimport FoundationNetworking\n#endif\n```\n\n### Have a different question?\n\nFeel free to shoot me an email, post a\n[question on StackOverflow](http://stackoverflow.com/questions/tagged/swxmlhash),\nor open an issue if you think you've found a bug. I'm happy to try to help!\n\nAnother alternative is to post a question in the [Discussions](https://github.com/drmohundro/SWXMLHash/discussions).\n\n## Changelog\n\nSee [CHANGELOG](CHANGELOG.md) for a list of all changes and their corresponding\nversions.\n\n## Contributing\n\nSee [CONTRIBUTING](CONTRIBUTING.md) for guidelines to contribute back to\nSWXMLHash.\n\n## License\n\nSWXMLHash is released under the MIT license. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrmohundro%2FSWXMLHash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrmohundro%2FSWXMLHash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrmohundro%2FSWXMLHash/lists"}