Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Nodal

Nodal is a Swift library for working with XML documents using DOM-like trees. It provides tools for parsing XML into a tree structure, manipulating the tree, and generating XML from the tree. The library is lightweight, efficient, and compatible with Linux, Windows and all Apple platforms.

Nodal is based on pugixml and adds a convenient Swift layer as well as support for XML namespaces. The entire public API has DocC documentation.

SwiftPlatforms

Installation

Add Nodal as a dependency in your Package.swift:

dependencies:[.package(url:"https://github.com/tomasf/Nodal.git", from:"1.0.0")]

Then, include Nodal in the target dependencies and make sure to enable C++ interoperability:

.target(
name:"YourTargetName",
dependencies:["Nodal"],
swiftSettings:[.interoperabilityMode(.Cxx)] // Nodal requires C++ interop
)

Usage

letdocument=Document()letroot= document.makeDocumentElement(name:"content", defaultNamespace:"http://tomasf.se/xml/example")letentry= root.addElement("entry")entry[attribute:"key"]="price"
entry.addText("499")letoutput=try document.xmlData()

Nodes

Nodal represents an XML document as a DOM (Document Object Model), which is a tree of nodes. Each node in the tree represents an element, text, comment, or other structural component of the XML document.

Nodes are tightly bound to the tree they belong to. Nodes cannot exist outside of a document; you cannot create a freestanding node and later add it. Instead, you create new nodes directly as children of an existing parent node. When a node is removed, it is immediately invalidated and cannot be reused or re-added elsewhere. Nodes can, however, be moved to a new position within the same document.

Unlike elements, attributes in Nodal are not represented as nodes. Instead, attributes are accessed and manipulated directly on elements. You retrieve and set the value of attributes by their names (qualified or expanded).

Namespaces

Nodal has support for namespaces for elements and attributes. This means you can assign expanded names (namespace URI + local name) to them and the corresponding qualified name will be set for you.

element.addElement("weight", namespace:"http://tomasf.se/xml/example")

This presumes the namespace has been declared and assigned a prefix in that element or one of its ancestors. If not, Nodal will use a temporary qualified name and fill the final one in once you’ve declared the namespace. Attempting to generate XML for a document with unresolved namespaces throws an error.

root.declareNamespace("http://tomasf.se/xml/example", forPrefix:"ex")

If you prefer to work without namespaces, that will work just fine, too.

XPath

XPath is a language for querying and selecting nodes from an XML document. It allows you to write expressions to locate elements and attributes efficiently.

Example Usage

letdocument=tryDocument(string:"""<catalog> <book id="bk101"> <title>XML Developer's Guide</title> </book> <book id="bk102"> <title>Midnight Rain</title> </book></catalog>""")letquery=tryXPathQuery("//book[@id='bk101']/title")iflet title = query.firstNodeResult(with: document)?.node?.textContent {print("Book title:", title) // Outputs "XML Developer's Guide"
}

While Nodal supports XML namespaces when working with the DOM, its XPath implementation does not support namespaces. This limitation arises from pugixml. To work with elements and attributes in documents that use namespaces, you must use their qualified names in your XPath expressions.

Value Serialization

Nodal provides protocols for serializing Swift values to and from XML. The XMLValueCodable protocol handles encoding and decoding values as strings (for attributes and text content), while XMLElementCodable handles encoding and decoding entire elements.

Built-in Type Support

Common types like Int, Double, Bool, String, UUID, URL, Date, and Data conform to XMLValueCodable out of the box:

letroot= document.makeDocumentElement(name:"item")
root.setValue(42, forAttribute:"count")
root.setValue(UUID(), forAttribute:"id")
root.setValue(Date.now, forAttribute:"created")letcount:Int=try root.value(forAttribute:"count")

Configurable Formats

You can configure how Date and Data values are serialized by setting properties on the document:

document.dateFormat =.iso8601 // Default, e.g. "2024-01-15T10:30:00Z"
document.dateFormat =.secondsSince1970 // Unix timestamp
document.dateFormat =.millisecondsSince1970
document.dataFormat =.base64 // Default
document.dataFormat =.hex // Hexadecimal encoding

Custom Types

Conform your own types to XMLValueCodable for string-based serialization, or XMLElementCodable for element-based serialization:

structPoint:XMLValueCodable{varx:Doublevary:Doublefunc xmlStringValue(for node:Node)->String{"\(x),\(y)"}init(xmlStringValue:String, for node:Node)throws{letparts= xmlStringValue.split(separator:",")guard parts.count ==2,let x =Double(parts[0]),let y =Double(parts[1])else{throwXMLValueError.invalidFormat(expected:"x,y", found: xmlStringValue)}self.x = x
self.y = y
}}

Contributions

Contributions are welcome! If you have ideas, suggestions, or improvements, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License, and so is pugixml. See the respective LICENSE files for details.

About

Cross-platform Swift XML library with a DOM interface

Topics

Resources

Stars

5 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages