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

XML Exporter: Generate element names for a fixed locale without breaking other exporter behavior #8205

Closed
stolp opened this issue Dec 26, 2021 · 15 comments · Fixed by #9689 or #9700
Closed
Assignees
Milestone

Comments

@stolp
Copy link
Contributor

stolp commented Dec 26, 2021

Description

In my multi-lingual application, I export tables to XML output and other formats like PDF and XLSX. The table column header string changes with the selected language.

The current implementation of DataTableXMLExporter derives tag names in the XML output from the corresponding column header value, which change according to the current locale setting used in the application.

This leads to different XML element names in the output for different locale settings, which really makes no sense at all.

When I set a fixed language exportHeaderValue string for the XMLTableExporter it will also appear for PDF, XSLX and other formats, so the user will stumble about column headers in a wrong language there.

The application is currently using PrimeFaces 11.

Describe the solution you would like

Clearly, element names in the XML exporter and table headers in PDF/XLSX are two different things. I am looking for a way to specify both without having cross-dependencies between them.

One quick idea for a solution would be to default to a single locale in this case, which has the benefit to not having to add extra element name information on each column.

Can this be circumvented by extending DataTableXMLExporter?

I think I need to override Exporter.exportValue(...) for this, but I am lost on how to force the locale to use there.

Would it make sense to at least pin down the locale used for element tags by an option to DataTableXMLExporter?

Whatever the solution is, it has to be on a per-Exporter basis, just targeting the XML export.

@melloware
Copy link
Member

melloware commented Jan 13, 2023

@stolp i have looked at this and have no real good idea on how to make this work without making it really hacky. Did you have any thoughts on how?

@stolp
Copy link
Contributor Author

stolp commented Jan 13, 2023

Maybe the DataTableXMLExporter can be told by an additional option to use the column id instead of the column header?
At least this one is fixed and does not change with the locale, which is what we want here.

Alternatively, an additional, dedicated facet comes to mind here. But this perhaps would be more effort to implement.

@melloware
Copy link
Member

Oh I think I like the ID aspect. It will always be the same and won't cause us to have to do anything funky just basically use the ID instead if its set. Let me look at that!

@melloware melloware self-assigned this Jan 13, 2023
@melloware melloware added this to the 13.0.0 milestone Jan 13, 2023
@stolp
Copy link
Contributor Author

stolp commented Jan 13, 2023

We may need to add some kind of normalization to make sure that the generated XML is valid. I am not sure if the JSF-id constraints fully match the XML element name constraints.

@melloware
Copy link
Member

usage:

 <p:dataExporter type="xml" target="tbl" fileName="products" useLocale="false"/>

TRUE (default):

<tbl>
	<product>
		<code>nvklal433</code>
		<name>Black Watch</name>
		<category>Accessories</category>
		<quantity>61</quantity>
		<price>$72.00</price>
	</product>

FALSE:

<?xml version="1.0"?>
<tbl>
	<product>
		<j_id_9h>waas1x2as</j_id_9h>
		<j_id_9k>Headphones</j_id_9k>
		<j_id_9n>Electronics</j_id_9n>
		<j_id_9q>8</j_id_9q>
		<j_id_9t>$175.00</j_id_9t>
	</product>

@stolp
Copy link
Contributor Author

stolp commented Jan 13, 2023

Nice! I have a comment here:

Will this also automatically work for the other data-exporters like Excel?

If yes, maybe it is better not to have that activated?

If no, maybe the naming of the useLocal parameter should reflect that this is for the XML export only, like in xmlColumnElementNames="header|id" (or something shorter).

This way, we may add an additional column facet option if we ever feel the need.

As a matter of fact, in the long run a facet would be the ideal solution for my use case as my current id scheme has column ids like e.g. "priceColumn" which is not the prettiest solution. Nonetheless in both scenarios I will have to fix that in my sources one way or the other, so this is not overly important.

What do you think?

@melloware
Copy link
Member

melloware commented Jan 13, 2023

Hmmm it already tries the header facet and exportHeaderValue is there any reason you are not using exportHeaderValue ?

You should be able to do this right now

<p:column headerText="#{localized.label}" exportHeaderValue="Static Header No Matter The Language" />

Have you tried that?

So adding ANOTHER facet doesn't make sense to me?

Or are you saying if you had an exportHeader facet and you had a property per exporter like useExportHeadreFacet it would respect that? To me that would be confusing if a user had...

<f:facet name="exportHeader">Hello</f:facet> but it did not take effect unless you turned it on with the <p:dataExporter> property. Feels like way too many switches and options and people will wonder why the facet is or isn't being used?

@stolp
Copy link
Contributor Author

stolp commented Jan 14, 2023

The exportHeaderValue would affect the other export formats as well, but we only want to change the XML exporter behavior. The default behavior is fine for all the other formats (PDF/XSLX). exportHeaderValue is fine, as long as I want to sacrifice localization in all my export formats. I remember that we were discussing this before.

Adding another facet definitely makes sense here, as the XML exporter actually requires this additional information.
Perhaps even a potential future JSON exporter would be requiring it as well, given that sadly XML is loosing ground as the lingua franca.

One can argue that the JSF id is enough for that purpose, but it is more of a hack for me as we are mixing semantics of the id field here. Users should be able to apply the id naming schemes of choice without having to adapt them to an exporter requirement.

My proposition is to have something like this:

<p:column headerText="#{localized.label}">
  <f:facet name="exportElement">hello</f:facet>
</column>

The exportElement facet will only be picked up by the XML exporter and will be ignored by the existing other exporters. If it is missing, the current mechanism will apply. The name of the facet would still need to be discussed.

I hope I could clear this up.

@melloware
Copy link
Member

How about exportTag instead of exportelement that way it would be generic for json too? I think I like this and it would clean up the code. No need to use extra Boolean property like I added just detect it in the xml transformer only if it exists

Let me update.

@stolp
Copy link
Contributor Author

stolp commented Jan 14, 2023

Thinking of it, there is nothing speaking against having an exportTag attribute and forgetting about the facet.

@melloware
Copy link
Member

melloware commented Jan 14, 2023

Even better and cleaner. I will submit a PR

@stolp
Copy link
Contributor Author

stolp commented Jan 14, 2023

We should also consider what to do with the tag names of the document and the 'rows'.

@melloware
Copy link
Member

melloware commented Jan 15, 2023

OK so for the document it uses this

writer.append("<" + table.getId() + ">\n");

Which should not change per locale right?

For rows it looks like it uses the var which should also not change per locale right?

((PrintWriter) document).append("\t<" + table.getVar() + ">\n");

@stolp
Copy link
Contributor Author

stolp commented Jan 15, 2023

Yes, and I can fully understand if you don't want to add two additional attributes to the datatable, which already has way more than is good.

But for the sake of consistency and completeness, adding exportTag and exportRowTag would be the cleanest solution here. Again, semantics are different for these.

@melloware
Copy link
Member

I can live with that. You are right it would make sense to control
The row tag.

@melloware melloware changed the title DataTableXMLExporter: Generate element names for a fixed locale without breaking other exporter behavior XML Exporter: Generate element names for a fixed locale without breaking other exporter behavior Jan 16, 2023
melloware added a commit to melloware/primefaces that referenced this issue Jan 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment