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

Rename Root::append_child to Root::set_child? #56

Open
dvtomas opened this issue Dec 7, 2017 · 8 comments
Open

Rename Root::append_child to Root::set_child? #56

dvtomas opened this issue Dec 7, 2017 · 8 comments

Comments

@dvtomas
Copy link

dvtomas commented Dec 7, 2017

    {
        let doc = package.as_document();
        let hello = doc.create_element("hello");
        let world = doc.create_element("world");
        doc.root().append_child(hello);
        doc.root().append_child(world);

        let stdout = &mut io::stdout();
        format_document(&doc, stdout).ok().expect("unable to output XML");
        stdout.flush();
    }

expected output: <?xml version='1.0'?><hello/><world/>
actual output as of v. 0.2.6. : <?xml version='1.0'?><world/>

Is this a bug in the code or in my expectations?

@dvtomas
Copy link
Author

dvtomas commented Dec 7, 2017

To answer myself: XML must have exactly one root element, so the behavior of the code is probably correct. Perhaps it would make sense to rename append_child to set_root to avoid confusion?

@shepmaster shepmaster changed the title how does root().append_child work? Rename Root::append_child to Root::set_child Dec 7, 2017
@shepmaster shepmaster changed the title Rename Root::append_child to Root::set_child Rename Root::append_child to Root::set_child? Dec 7, 2017
@shepmaster
Copy link
Owner

Yup, there can only be a single element at the top. However, there can be multiple other types of nodes, notably comment and processing instruction nodes.

The name of the method is indeed unfortunate. At the very least, the documentation should be updated to clarify that subsequent elements take the place of previous ones.

I'm a little loathe to actually change the name as it is correct for 2/3 types you can append...

@dvtomas
Copy link
Author

dvtomas commented Dec 8, 2017

Ahh, makes sense now, thanks for clarification. Yeah, I guess just explaining this in the function documentation would do the job.

@dvtomas
Copy link
Author

dvtomas commented Dec 8, 2017

On a related note, I noticed that there is no newline after the <?xml ...> declaration from a format_document output. I assume that it does not matter semantically, but is it possible to somehow add it just for human viewing pleasure, prehaps by doing some kind of append_child(newline node) or something? Sorry if this is a dumb question, I'm not an expert on XML specification...

@shepmaster
Copy link
Owner

it does not matter semantically

That's correct. It is better from a storage / transfer point of few — the less bytes the better.

somehow add it just for human viewing pleasure

You can always write the newline yourself to whatever output you are using. In your example, it's easy:

let stdout = &mut io::stdout();
format_document(&doc, stdout).ok().expect("unable to output XML");
println!();
stdout.flush();

There's been some discussion about having a "pretty" mode for format_document that would also indent nested children, which this could conceivably also do.

@dvtomas
Copy link
Author

dvtomas commented Dec 8, 2017

Aha, I didn't even realize the output is not pretty-printed. When I started toying with sxd-document, I parsed an already pretty-printed document first and then used the writer to write it again. When I saw the pretty printed output, I thought that it was a writer feature, I didn't realize it was just preserving the whitespace in the input (which probably is the case).

For my use-case, a pretty printed output would be very useful, but that belongs to another issue.

As far as I'm concerned about this issue, just stating the potentially confusing behavior in the documentation would be enough for me.

But, if you really wished to make some changes, I think type-wise it would be probably more correct to change

pub struct Root {
    children: Vec<ChildOfRoot>,
}

pub enum ChildOfRoot {
    Element(*mut Element),
    Comment(*mut Comment),
    ProcessingInstruction(*mut ProcessingInstruction),
}

into

pub struct Root {
    element: *mut Element
    children: Vec<ChildOfRoot>,
}

pub enum ChildOfRoot {
    Comment(*mut Comment),
    ProcessingInstruction(*mut ProcessingInstruction),
}

and modify the accessors/mutators accordingly, but the questions is, whether the benefits are worth the troubles (breaking backwards compatibility, changing API).

@shepmaster
Copy link
Owner

The problem with your proposed structure is that you are allowed to put comments/PIs before and after the element proper. All of these are valid:

<!-- one --><!-- two --><thing />
<!-- one --><thing /><!-- two -->
<thing /><!-- one --><!-- two -->

@dvtomas
Copy link
Author

dvtomas commented Dec 8, 2017

OK, then something like

pub struct Root {
   pre_children: Vec<ChildOfRoot>, 
   element: *mut Element
   post_children: Vec<ChildOfRoot>,
}

would (I hope) match the XML model 1:1. If it's worth the added complexity is hard to say, I don't have an opinion on that.

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

No branches or pull requests

2 participants