-
Notifications
You must be signed in to change notification settings - Fork 4
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
Add Writer.embed function to allow writing pre-formed XML without escaping anything #39
Conversation
escaping anything Useful for embedding one XML fragment into another
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! I think this is a good function to have. I have a couple suggestions to expand the possible use-cases for it. Also, it should be added to GenericWriter
so users of that API can call it:
Lines 433 to 471 in ee8e09b
pub fn GenericWriter(comptime SinkError: type) type { | |
return struct { | |
writer: Writer, | |
pub const WriteError = Writer.WriteError || SinkError; | |
pub inline fn bom(writer: *@This()) WriteError!void { | |
return @errorCast(writer.writer.bom()); | |
} | |
pub inline fn xmlDeclaration(writer: *@This(), encoding: ?[]const u8, standalone: ?bool) WriteError!void { | |
return @errorCast(writer.writer.xmlDeclaration(encoding, standalone)); | |
} | |
pub inline fn elementStart(writer: *@This(), name: []const u8) WriteError!void { | |
return @errorCast(writer.writer.elementStart(name)); | |
} | |
pub inline fn elementEnd(writer: *@This(), name: []const u8) WriteError!void { | |
return @errorCast(writer.writer.elementEnd(name)); | |
} | |
pub inline fn elementEndEmpty(writer: *@This()) WriteError!void { | |
return @errorCast(writer.writer.elementEndEmpty()); | |
} | |
pub inline fn attribute(writer: *@This(), name: []const u8, value: []const u8) WriteError!void { | |
return @errorCast(writer.writer.attribute(name, value)); | |
} | |
pub inline fn pi(writer: *@This(), target: []const u8, data: []const u8) WriteError!void { | |
return @errorCast(writer.writer.pi(target, data)); | |
} | |
pub inline fn text(writer: *@This(), s: []const u8) WriteError!void { | |
return @errorCast(writer.writer.text(s)); | |
} | |
}; | |
} |
src/Writer.zig
Outdated
switch (writer.state) { | ||
.after_structure_end, .text => {}, | ||
.element_start => try writer.raw(">"), | ||
.start, .after_bom, .after_xml_declaration, .end => unreachable, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switch (writer.state) { | |
.after_structure_end, .text => {}, | |
.element_start => try writer.raw(">"), | |
.start, .after_bom, .after_xml_declaration, .end => unreachable, | |
} | |
switch (writer.state) { | |
.start, .after_bom, .after_xml_declaration, .after_structure_end, .text, .end => {}, | |
.element_start => try writer.raw(">"), | |
} |
I don't see any reason to restrict this function to operate only inside the root element: it's reasonable that someone might want to use it to embed a DTD at the beginning of the document, for example, which isn't currently possible with the other methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point, I was thinking too narrowly about my own use case, embedding xml fragments inside an existing document. Fixed in f54c606
src/Writer.zig
Outdated
.start, .after_bom, .after_xml_declaration, .end => unreachable, | ||
} | ||
try writer.raw(s); | ||
writer.state = .after_structure_end; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
writer.state = .after_structure_end; | |
writer.state = switch (writer.state) { | |
.start, .after_bom, .after_xml_declaration => .after_xml_declaration, | |
.element_start, .after_structure_end, .text => .text, | |
.end => .end, | |
}; |
Once this function is opened up to work in more scenarios, other possible states also need to be handled. In this suggestion, I chose text
as the ending state within the root element to avoid indentation if another element is started right after this function (to maximize the possible uses, including for embedding raw text nodes).
@ianprime0509 thanks for the review, I'm glad this can be useful. I'll apply your suggestions shortly! |
Fixes: ianprime0509#39 (review) Make the "embed" function more permissive about contexts in which it's used, as this makes it more flexible Fixes: - ianprime0509#39 (comment) - ianprime0509#39 (comment)
Add a 'testbed' facility for writing more test.
Thanks again @ianprime0509 I've added your suggestions in f54c606 I've also started adding tests for Writer as there didn't seem to be any 1a0355a, but happy to drop this commit or move it to a new PR if it's not something you're interested in right now. |
Awesome, thanks! Yeah, I haven't added any tests or proper doc comments to the writer yet, unfortunately. I'll probably go a slightly different direction with the tests when I get to it (focusing on having one self-contained doctest for each function, similar to the current reader tests), but I think what you have for now is a useful start. |
Useful for embedding one XML fragment into another