Library / SDK
drmohundro/SWXMLHash avatar
drmohundro/SWXMLHash

SWXMLHash for Swift XML parsing and indexed lookup

Simple XML parsing in Swift

1,467 stars209 forksSwiftMIT

At a glance

What is it?
SWXMLHash wraps Foundation's XMLParser with an indexer for element, attribute, and text lookups in Swift. It suits applications that want concise XML access, but its dictionary-of-arrays model and selective error detection require attention to document shape and malformed input.
Who is it for?
Swift developers should adopt SWXMLHash when XML is central to a small or moderate feature and indexed calls are preferable to handling XMLParser directly. Projects that require automatic malformed-document rejection, schema validation, or streaming consumption beyond SWXMLHash's lazy mode should verify those needs before adoption.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 24 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The XML access problem SWXMLHash addresses

SWXMLHash targets Swift applications that receive XML and need to retrieve values without manually coordinating the callbacks exposed by XMLParser, formerly known as NSXMLParser. Its central abstraction is an XMLIndexer that behaves conceptually like a dictionary of arrays. That representation is useful when a document contains repeated elements, because each lookup leads to a collection from which the caller can select an item by index.

The API is aimed at developers who already know the shape of their XML. A path such as `xml["root"]["header"]["title"].element?.text` maps element containment to chained subscripts. Repeated siblings are handled with another subscript, as in `xml["root"]["catalog"]["book"][1]["author"].element?.text`. This is more compact than writing parser callbacks for each level of a known document, although it does not remove the need to understand XML structure.

The project also exposes element text and attributes through the indexed model. That makes it relevant for feeds, configuration documents, metadata, and service responses whose relevant fields are nested under predictable names. SWXMLHash is not a general XML transformation framework according to the README. Its documented design centers on lookup and optional deserialization-related context rather than editing, serializing, or validating arbitrary XML documents.

XMLParser callbacks translated into an indexer

SWXMLHash is a wrapper around Apple's XMLParser. The parser processes an XML source, while SWXMLHash translates the resulting hierarchy into the indexer used by the public API. The README describes this as a translation from XML to a dictionary of arrays, inspired by SwiftyJSON, but the retained structure still reflects XML element names and their nesting rather than decoding directly into an application model.

A normal parse begins with `XMLHash.parse(xmlToParse)`. Subscript access follows the hierarchy. Attributes remain attached to their corresponding XML element, while text is reached through an element reference. This preserves the distinction between a missing lookup and the content of a selected node. The multiple-element example shows that repeated `<book>` nodes remain ordered and addressable, with index `1` selecting John in the documented example.

Configuration changes parser behavior without replacing the underlying parsing approach. Namespace processing is forwarded to the internal NSXMLParser instance. When enabled, an element written as `<h:table>` is returned as `<table>`. Case-insensitive lookup changes key matching, while an explicit encoding can be supplied for XML strings. The `userInfo` option supplies contextual information used during deserialization, although the README does not document a complete Codable mapping workflow.

Lazy processing is the notable alternative data path. `XMLHash.lazy(xmlToParse)` and `config.shouldProcessLazily = true` avoid loading the entire XML document into memory according to the README. That matters for large files, but the documentation notes an error-handling caveat without specifying its details, so malformed lazy input needs explicit verification in the consuming application.

Swift Package Manager setup and first indexed lookup

SWXMLHash documents Swift 6.0+, Xcode 16.0+, and deployment targets of iOS 11.0+, macOS 10.13+, tvOS 11.0+, or watchOS 4.0+. These requirements apply to the current README, while the installation snippet still uses the 7.0.0 dependency range. That discrepancy should be checked against `Package.swift` or the resolved dependency before an application pins production versions.

For Swift Package Manager, add the package reference shown in the README. This declares SWXMLHash as a package dependency beginning with version 7.0.0 under semantic version resolution. The stated effect of `swift build` is to fetch and compile the package for use in the project.

swift
dependencies: [
    .package(url: "https://github.com/drmohundro/SWXMLHash.git", from: "7.0.0")
]

After adding the dependency and importing SWXMLHash, the first parse can use the documented initialization API. The variable `xmlToParse` represents the XML string supplied by the application.

swift
let xml = XMLHash.parse(xmlToParse)

A lookup then follows the document's element hierarchy. Given the README's nested title example, the optional `element?.text` expression produces `"Foo"`.

swift
xml["root"]["header"]["title"].element?.text

Repeated elements require an additional index. For the documented catalog, index `1` selects John's `<author>` element rather than Bob or Mark.

swift
xml["root"]["catalog"]["book"][1]["author"].element?.text

This API makes a missing path evident through an optional value, but it does not by itself prove that the XML was valid. Applications should define how absent, duplicate, or unexpectedly named elements affect their state.

Large documents, namespaces, encoding, and parser errors

Configuration is entered through `XMLHash.config`, after which a parse option is applied. For a large document, the README states that `shouldProcessLazily` can significantly increase parsing performance and avoid retaining the entire XML document in memory. A shorter `XMLHash.lazy` entry point exists for the same broad mode, so a basic application does not need to construct the full configuration closure merely to select lazy processing.

swift
let xml = XMLHash.config {
              config in
              config.shouldProcessLazily = true
          }.parse(xmlToParse)

Namespace processing can simplify lookups when qualified names would otherwise require the namespace portion. The documented tradeoff is loss of that namespace part from returned element names. Two distinct documents or branches that share a local name but belong to different namespaces can therefore require an application-specific identity strategy beyond a plain local-name lookup. The README does not document namespace URI indexing.

The `encoding` option defaults to `String.encoding.utf8` and can explicitly identify the encoding of an XML string. `caseInsensitive` defaults to `false`, which aligns lookups with XML's case-sensitive naming. `userInfo` defaults to an empty dictionary and carries contextual values for deserialization.

Error detection is disabled by default. When `detectParsingErrors` is enabled, `parse` can return `XMLIndexer.parsingError` for parsing problems. The README does not state which malformed constructs this mode catches or whether all parser errors are surfaced, so treating it as a complete XML conformance validator would exceed its documented scope.

Where the indexer model becomes a limitation

The largest design constraint is SWXMLHash's dictionary-of-arrays abstraction. It works well for known paths and repeated sibling selection, but XML can also contain mixed content, attributes with namespace qualification, varying child order, and values whose meaning depends on schema. The README does not document facilities for XSD validation, schema-aware decoding, XML mutation, or serialization back to XML. Those omissions matter when XML is the application's interchange contract rather than a simple input format.

Malformed input is another boundary. Because `detectParsingErrors` defaults to `false`, a basic parse does not guarantee that every parsing issue will produce an explicit error value. The README gives the compatibility reason: many users attempt to parse HTML with the library. That does not make SWXMLHash an HTML parser. XML and HTML have different syntax requirements, and the README gives no compatibility guarantee for HTML documents.

Large-file handling has a similar qualification. Lazy mode is presented as a memory and performance option, but the README explicitly mentions an error-handling caveat without explaining it. A project processing untrusted or frequently truncated documents should not assume that it can switch on lazy processing and obtain the same error behavior as an eager parse.

Swift version and deployment targets can also constrain adoption. The README requires Swift 6.0+ and Xcode 16.0+, with minimum Apple platform versions listed there. An older Swift toolchain cannot be assumed to resolve the current package. The repository includes alternate `[email protected]`, `[email protected]`, and `[email protected]` files, but the README does not describe their exact version-selection behavior.

XMLParser and multi-platform dependency choices in SWXMLHash

The direct alternative is Apple's XMLParser. Both approaches ultimately parse XML, but SWXMLHash wraps the lower-level parser and adds indexed traversal, array-style sibling selection, configuration helpers, and Codable-related context. XMLParser requires the caller to implement parser callbacks and track the current document state. SWXMLHash removes much of that callback coordination at the cost of a library layer and a document model centered on subscripts.

For a project that already owns parser state, custom validation, or event-specific processing, direct XMLParser control may be easier to justify. SWXMLHash is more appropriate when a small part of a Swift application needs readable access to known XML paths. Its lazy mode also offers a documented route for avoiding a full in-memory document, although it does not replace a separately designed streaming architecture.

SWXMLHash supports four documented installation routes. Swift Package Manager is the repository's primary modern option. CocoaPods is also documented through a `Podfile` containing `pod 'SWXMLHash', '~> 7.0.0'`. Carthage uses a `Cartfile` entry, while manual installation can copy relevant Swift files or add `SWXMLHash.xcodeproj` to a workspace. The README recommends git submodules for manual dependency tracking because they record the dependency commit.

The project is MIT-licensed, which permits reuse and modification under that license's conditions. This is not legal advice. Consumers still need to retain the required license notice and review the repository's `LICENSE` file for their distribution context. The last push was on 2026-09-29, so the repository was not archived in the recorded repository status. Upgrade work should account for Swift package version selection and the documented jump from 7.0 installation examples to the 8.1.1 release record.

Editorial conclusion

Swift developers should adopt SWXMLHash when XML is central to a small or moderate feature and indexed calls are preferable to handling XMLParser directly. Projects that require automatic malformed-document rejection, schema validation, or streaming consumption beyond SWXMLHash's lazy mode should verify those needs before adoption. The first integration check is whether the expected element names, repeated nodes, attributes, namespace behavior, and parsing errors match the application's real XML documents.

Frequently asked questions

How do I install SWXMLHash in a Swift project?

The README documents installation with Swift Package Manager, CocoaPods, Carthage, or manual file inclusion. Its Swift Package Manager example adds `https://github.com/drmohundro/SWXMLHash.git` with a package requirement beginning at `7.0.0`.

How do I read repeated XML elements with SWXMLHash?

Repeated sibling elements can be selected with an array subscript. The documented example uses `xml["root"]["catalog"]["book"][1]["author"].element?.text` to retrieve the second book's author.

Does SWXMLHash detect malformed XML by default?

No. `detectParsingErrors` defaults to `false`; when enabled, `parse` can return `XMLIndexer.parsingError` when parsing issues are detected.

Official sources

  1. drmohundro/SWXMLHash on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/drmohundro-swxmlhash.svg)](https://hysenlabs.com/projects/drmohundro-swxmlhash)

Was this useful?