feat: Implement XML node abstractions with validation and serialization - #17
Merged
Conversation
This commit introduces the core XML node abstractions for tags, declarations, attributes, and text content. It adds reusable interfaces and concrete node classes with serialization, escaping, and child-node support for building basic XML documents.
Fix XML attribute serialization by escaping '<' as '<' when writing attribute values. This keeps attribute contents valid XML and prevents malformed output when attribute text contains comparison operators or angle brackets.
This change adds a shared XML name validator and enforces it when creating tag names and setting attributes. Invalid names now throw std::invalid_argument instead of being accepted silently, preventing malformed XML content at the API boundary.
Add XmlCharacter.hpp (isValidXmlCharacterData) to enforce XML 1.0 character rules (reject control chars < 0x20 except tab/newline/carriage return). Use it in IAttributes to validate attribute values and in XmlTextContent (ctor, setter, append) to validate text content. Also add necessary includes and throw std::invalid_argument on invalid input.
The XML attribute accessor was returning std::optional<std::string_view>, which can dangle when the underlying stored value is not guaranteed to outlive the call. This change returns a copied std::string instead, making the API safe and consistent with callers that need an owned value.
Add cycle detection to XmlTagNode::append: attempting to append a child that would create a cycle now throws std::invalid_argument. Implement containsNode (iterative DFS with a visited set) to detect reachability. Include necessary headers (<stdexcept>, <unordered_set>).
This change enforces XML declaration correctness by requiring the tag name to be `xml`, validating required `version` values (`1.0` or `1.1`), and rejecting unsupported attributes, invalid encoding names, and invalid standalone values during serialization. It also serializes declarations in the standard `<?xml ...?>` form with optional `encoding` and `standalone` attributes.
These headers were using std::string_view and related standard library types without including the required headers. This patch adds the missing includes to the XML node interfaces and content classes so they compile cleanly and remain self-contained.
Serialize XML attributes in a deterministic key order instead of the underlying hash-map order so output is stable and predictable. The change also keeps attribute escaping intact while writing values. Minor formatting/include-order cleanups were applied to the XML declaration and tag headers.
Replace the unordered attribute container with std::map and remove the extra sort step during XML serialization. This keeps attribute output deterministic and in key order while simplifying the implementation and reducing unnecessary work.
Remove handling that converted '"' and '\'' to " and ' in XmlTextContent output. Quotes are valid in XML character data and should only be escaped in attribute values; this avoids unnecessary escaping or double-encoding in text nodes. Change made in include/xtrpg/xml/node/XmlTextContent.hpp.
The stream extraction overload for XmlTextContent was appending a newline after each read line. This patch removes that delimiter so a single line is appended exactly as read, preserving the original text content without introducing extra line breaks.
This change updates XML attribute escaping to encode tab, newline, and carriage return characters as XML numeric references (`	`, `
`, `
`). This ensures attribute values remain valid and safe when serialized into XML.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.