Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support XML Namespaces in Writer #40

Closed
MFAshby opened this issue Oct 26, 2024 · 4 comments · Fixed by #41
Closed

Support XML Namespaces in Writer #40

MFAshby opened this issue Oct 26, 2024 · 4 comments · Fixed by #41

Comments

@MFAshby
Copy link
Contributor

MFAshby commented Oct 26, 2024

Related to #10

Currently the Writer API does not explicitly support namespaces.

It's possible to mostly work around it by adding the appropriate XML attributes:

    fn write(self: Multistatus, wtr: *xml.Writer, a: std.mem.Allocator) !void {
        try wtr.elementStart("multistatus");
        try wtr.attribute("xmlns", "DAV:");
        try wtr.attribute("xmlns:c", "urn:ietf:params:xml:ns:carddav");
...

however, this means it's now down to the library user to track which namespace prefix is used for which namespace and specify element names with the appropriate prefix in child nodes. The prefix has no meaning except to identify the namespace.

Ideally the writer API would handle this for us; when calling Writer.elementStart there should be an option to specify the namespace of the current element; as well as optionally setting the current default and non-default namespaces. The writer could handle assigning prefixes to namespaces.

@ianprime0509
Copy link
Owner

I think allowing the namespace prefix to be auto-generated is a good idea, although I would also like to allow optionally assigning a custom prefix to the namespace, to support a more human-readable output format for cases where certain namespaces have conventional prefixes. What I'm starting on to make more progress towards #10 is planned to look something like this:

  • writer.bindNs("ns", "http://example.com") - binds a namespace prefix (inside an element_start, this will emit an xmlns:ns attribute; otherwise, it will store it in a "pending" list to be bound the next time an element is started, which is required to handle a case like <ns:local xmlns:ns="...">...)
  • writer.elementStart("ns:local") - works the same as it does now
  • writer.elementStartNs("http://example.com", "local") - looks up the bound (or pending) namespace prefix for http://example.com and uses it, or makes up and binds a new one if there isn't one already
  • writer.attribute("ns:local", "text") - works the same as it does now
    • writer.attribute("xmlns", "http://example.com") or writer.attribute("xmlns:ns", "http://example.com") - additionally keeps track of the new namespace binding
  • writer.attributeNs("http://example.com", "local", "text") - does the same sort of processing as elementStartNs

(just as Reader has a namespace_aware option currently which can be set to false to disable namespace processing, Writer will also get the same option, making all the Ns-suffixed functions illegal and skipping any extra namespace processing of elements and attributes)

Another goal of #10 is to have configurable safety checks which should ideally be able to catch any well-formedness errors when using any of these functions, but that's a longer term goal and I don't think I'll include that in the initial implementation of this.

@MFAshby
Copy link
Contributor Author

MFAshby commented Oct 29, 2024

that sounds great :D

I've hacked something together here which allows introducing namespaces and applying namespaces to element names (not attributes yet) with elementStartNs. It generates prefixes for you but doesn't yet allow user-supplied ones. I'll tweak it a bit and see if I can bring it into line with your suggested API.

@ianprime0509
Copy link
Owner

Thanks! I actually have an initial version locally, where I'm also planning to fill out the test suite and doc comments, but it'll likely be a few days until it's completely ready, though.

ianprime0509 added a commit that referenced this issue Oct 31, 2024
Closes #40

In addition to the new namespace-aware functions, this commit brings several other enhancements:

- The element name has been removed as an argument of `elementEnd`. The writer now keeps track of the current open element automatically.
- Doctests have been added for all public writer functions.
- Doc comments have been added for all public writer functions.
@ianprime0509
Copy link
Owner

I opened #41 with an initial implementation of the API outlined above. All the tests I added are passing, but I'm going to take another look at it later before merging to make sure I didn't miss anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants