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

StAXEncoder.writeAttribute() putting attributes on wrong element? #43

Open
jsbiff opened this issue Dec 27, 2024 · 3 comments · May be fixed by #44
Open

StAXEncoder.writeAttribute() putting attributes on wrong element? #43

jsbiff opened this issue Dec 27, 2024 · 3 comments · May be fixed by #44

Comments

@jsbiff
Copy link

jsbiff commented Dec 27, 2024

In the following code, if xmlw is a normal StAX XMLStreamWriter object, the xhtml comes out correctly, that is, with the "rel" and "href" attributes attached to the "link" element:

       xmlw.writeStartElement("head");
	xmlw.writeEmptyElement("link");
	xmlw.writeAttribute("rel", "stylesheet");
	xmlw.writeAttribute("href", "css/xmlwriter01.css");
	xmlw.writeStartElement("title");
	xmlw.writeCharacters(title);
	xmlw.writeEndElement();
	xmlw.writeEndElement();

I ran this program (there's more to it - like setting encoding and fidelity options on the factory object - including the option EncodingOptions.INCLUDE_OPTIONS so that the resulting Exi file would have the options needed to decode it) , again, but this time I had xmlw setup as a StAXEncoder object, to write out the xhtml as an exi file.

I then used the exificient-gui program to decode to an XML file, and what I discovered is that the two attributes that should have been on the "link" element, ended up on the element AFTER the link element (which was a "title" element).

I think this might be a bug?

@danielpeintner
Copy link
Member

I think the problem is that the current implementation assumes that the following line

xmlw.writeEmptyElement("link");

is a start element followed by an end element.
Hence, no attributes.

see

public void writeEmptyElement(String prefix, String localName,
String namespaceURI) throws XMLStreamException {
this.writeStartElement(prefix, localName, namespaceURI);
this.writeEndElement();
}

If I get your message (code snippet) right, it might be possible that in StAX terms an empty element might have attributes, right?
If so the implementation of https://github.com/EXIficient/exificient/blob/master/src/main/java/com/siemens/ct/exi/main/api/stream/StAXEncoder.java is not correct.

Note: a workaround would be to use the following sequence.

xmlw.writeStartElement("head");
xmlw.writeStartElement("link");
xmlw.writeAttribute("rel", "stylesheet");
xmlw.writeAttribute("href", "css/xmlwriter01.css");
xmlw.writeEndElement(); // link
xmlw.writeStartElement("title");
xmlw.writeCharacters(title);
xmlw.writeEndElement(); // title
xmlw.writeEndElement(); // head

@jsbiff
Copy link
Author

jsbiff commented Dec 27, 2024

@danielpeintner "If I get your message (code snippet) right, it might be possible that in StAX terms an empty element might have attributes, right?"

That sounds about right. Yes, I could do a non-empty element, but, yes, StAX allows to add attributes to an empty element - because an empty element is still allowed to have attributes. It would end up looking, in standard xml text serialization, as:

<link rel="stylesheet" href="css/xmlwriter01.css" />

The "end" of the element seems to happen automatically in the JDK implementation, when a non-attribute event happens after a writeEmptyElement. So, in this example, when xmlw.writeStartElement("title"); is run, the empty element gets closed. I would expect "characters", "PCData" or "EndElement" events to also signal the end of the empty element (note that if an empty element is followed by an endelement, I don't think the endelement closes the empty element - rather it would close the parent element of the empty element; the reason I think this is, that as an experiment, I tried adding a writeEndElement after my empty element, and this caused a cascade error later in the app, when it got to the very last writeEndElement for the "html" element - the error indicated there was no element to close).

The interesting thing here is, if I take that text serialization from my program, encode it to exi with exificient-gui, then decode it again to xml, it preserves the link as an empty element with attributes. I guess that probably the exificient-gui app uses a different API like the SAX writer, which handles empty elements correctly.

So, in summary, yes, I think you've identified this correctly as a bug in StAXEncoder.java.

@danielpeintner danielpeintner linked a pull request Jan 10, 2025 that will close this issue
@danielpeintner
Copy link
Member

Please take a look at #44
It should fix the issue.

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