Avoid panics when element doesn't exist
On xml document, I want to do:
doc.SelectElement("//path1").SetText("reset")
doc.SelectElement("//path2").SetText("reset")
doc.SelectElement("//path3").SetText("reset")
But it is possible that some xpath doesn't exist. in this case, I just ignore it without panicking. Can we add something add something that return default value if no found. for example:
doc.SelectElement("//path1").NotNil().SetText("reset")
doc.SelectElement("//path2").NotNil().SetText("reset")
doc.SelectElement("//path3").NotNil().SetText("reset")
PS: I know that I can check if it is nil or not but it is for avoiding boilerplate.
In order to do this properly, the API would need to stop returning a pointer to an Element. That would be a breaking change, so I cannot really do this.
You could achieve a similar effect by adding your own helper function:
func NotNil(e *etree.Element) *etree.Element {
if e == nil {
return etree.NewElement("");
}
return e
}
Then you could do this:
NotNil(doc.SelectElement("tag")).SetText("reset");
Alternatively, you could wrap the SelectElement function like this:
func SelectElementOrDefault(e *etree.Element, tag string) *etree.Element {
e = e.SelectElement(tag)
if e == nil {
return etree.NewElement("");
}
return e
}
Then you could do this:
SelectElementOrDefault(doc, "tag").SetText("reset");
These proposals may not have the same fluent style your proposal has, but it would achieve the same result without requiring an API-breaking change to etree.
(Also, I think you may have meant FindElement instead of SelectElement, although the issues are the same.)
Thank for your proposed code (this is what I already did).
From your point of view, this code is considered as a breaking change? (as this function goes on to return a pointer)
func (e *etree.Element) NotNil() *etree.Element {
if e == nil {
return etree.NewElement("");
}
return e
}
If you think so, you can close this issue. And I use my boilerplate.
But overall, I want to thank you for this great library.
Huh. Thanks to you, today I learned that go functions can process a nil pointer receiver without a panic. I was under the impression that this was not possible.
Let me think about this further. I might be open to an API that allows the conversion of a nil element to an element with a caller-defined fallback tag. Maybe something like this:
func (e *Element) Fallback(tag string) *Element {
if (e == nil) {
return NewElement(tag)
}
return e
}
I finally got back to this. Sorry for the delay.
After thinking more about this, I realized your original proposal made more sense than my alternative proposal. It's actually pretty useless being able to specify a fallback or default tag for the dummy element.
I've implemented NotNil in the latest commit.
Thanks for the suggestion!