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

Form not populated with XML if minOccurs=0 #38

Open
groupmsl opened this issue Jun 19, 2020 · 8 comments
Open

Form not populated with XML if minOccurs=0 #38

groupmsl opened this issue Jun 19, 2020 · 8 comments

Comments

@groupmsl
Copy link

Hello,

I have an XSD with something like:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="andeContinuousIntegrationTools"> <xs:complexType> <xs:all> <xs:element name="automatedIceDeployment"> <xs:complexType> <xs:sequence> <xs:element name="getConfig" type="aidUpdateConfig" minOccurs="0" maxOccurs="unbounded"/> ... </xs:sequence> </xs:complexType> </xs:element> ... </xs:all> </xs:complexType> </xs:element> </xs:schema>

And I try and generate a populated html form with the following xml:
<?xml version="1.0"?><andeContinuousIntegrationTools><automatedIceDeployment><updateConfig name="jj" templateName="jkj" templateVersion="-1" deletePreviousVersion="false" deleteAllPreviousVersions="true"><general iceName="test" friendlyName="test" autoSwitcherAlias="true" autoLoggingDir="true" autoConfigurationDir="true"></general></updateConfig></automatedIceDeployment><morpheusAutoDeployment></morpheusAutoDeployment></andeContinuousIntegrationTools>

But this only generates an empty form. If I remove the minOccours="0" from my XSD though it does generate a populated form.

I don't want this section of XML to be required, but want it to populate a form if it is present in input XML. Is this possible?

@MichielCM
Copy link
Owner

It should work as you think. Can you try the latest release instead of the latest upload?

https://github.com/MichielCM/xsd2html2xml/releases

@groupmsl
Copy link
Author

I have been struggling to generate a form from XML at all using Python and lxml. I can generate from an XSD, so I think I'm just doing something wrong with my schema references. I have been testing this so far just using the tool on your website - is this running the latest release?

I will continue to try getting form generation working from Python today and report back.

@groupmsl
Copy link
Author

groupmsl commented Jun 22, 2020

With fresh eyes after a weekend I've quickly solved the issue converting XML to a form using Python which is good. I then tried using the latest commit to generate a form and and it behaves the same as the latest release (3.3), I can not generate a populated form if minOccurs=0

@groupmsl groupmsl reopened this Jun 22, 2020
@groupmsl
Copy link
Author

I've also come across another issue (which is kind of related):

I have an element in a sequence which has a minOccurs="2" maxOccurs="2". When this is converted from XSD to HTML, I only get one element, and no buttons to add or remove further.

@simonsirak
Copy link

Hi @MichielCM,

I am also getting the same issue as @groupmsl. Consider the following small example (run locally with Saxon 10.1 and the latest release of xsd2html2xml, using Java). We have one mandatory child that has an optional age-element; 0 or more siblings, each with a mandatory choice between "how much older" or "how much younger"; 0 or more parents, each with a mandatory name-element. Specifically, consider the following (note specifically that the first sibling is omitted in the populated form, but not the first parent):

Inputs

XML:

<config>
    <child>
        <name>alice</name>
        <age>1</age>
    </child>
    <sibling>
        <older>4</older>
    </sibling>
    <sibling>
        <older>5</older>
    </sibling>
    <parent>
        <name>bob</name>
    </parent>
    <parent>
        <name>cecilia</name>
    </parent>
</config>

XSD:

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="config">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="child">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="name" type="xs:string"/>
                            <xs:element name="age" type="xs:string" minOccurs="0" maxOccurs="1"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="sibling" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:choice>
                            <xs:element name="older" type="xs:integer"/>
                            <xs:element name="younger" type="xs:integer"/>
                        </xs:choice>
                    </xs:complexType>
                </xs:element>
                <xs:element name="parent" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="name" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Output

I will only provide an image, since the source HTML would not be as simple to interpret. This was rendered on the latest stable release of Chrome:
image

Question

What could cause this issue? To me, it seems as if there is some sort of "off-by-one" issue (or something similar) which seems to affect complex elements that involve "choice" in some way, during population? I am not too familiar with the tool, so I cannot know for sure. But after examining html-populators.xsl, it seems as if there is some usage of previousElementSibling etc., which is what made me suspect this.

Any answers are greatly appreciated, and thank you for providing this very useful tool! 😄

@simonsirak
Copy link

Update: I think I found a potential cause for this, at least for the problem I faced. There were actually two issues that prevented population of a part of the form for me (only the first one is shown in the above example):

  1. This first one is with regards to my example above, i.e elements with minOccurs=0. Ensuring that the minimum number of element exist is done before filling in a specific xsl:choice. Specifically, all the contents of choices have been filled in beforehand (e.g "younger" or "older" in the above example), but the actual radio-input that specifies which choice to use remains unfilled until after the minimum number of elements is ensured (the order of operations is shown here). However, when enforcing the minimum number of elements, we only look for the first input and check that it has been filled. In the case of choices, the unfilled radio-input is before the actual filled in "sub-elements" in document order. As such, this is the element that we use to check whether any choice has been made. Since it is not filled in yet, ensureMinimum() assumes that this is a non filled-in element that can be safely removed.

My workaround for this one was to change the highlighted line to this:

&amp;&amp; Array.from(o.previousElementSibling.previousElementSibling.querySelectorAll("input, textarea, select")).filter((el) => {el.hasAttribute("data-xsd2html2xml-filled")}).length == 0) {

This instead checks that there is at least one filled sub-element in the element; if there is none, then it is deemed safe to remove. This solved my initial issue posted above.

  1. The second issue (not related to the example above) is not really related to the tool; I accidentally had a trailing space in one of my XSD-defined element names; that space was preserved in the tool, and subsequently led to this element not being added during population (because the tool explicitly looks for the name specified in XSD, which had a trailing space).

Hopefully any of these findings are helpful and allow you to properly render optional elements! These are what fixed it for me at least.

Again, thanks for making this tool available! It has been very helpful 🙏

@groupmsl
Copy link
Author

Hi @simonsirak ,

Thanks for all the info you added to this. I've done some digging based on what you've written and come to largely the same outcome. However, the fix you suggested didn't work for me in either Firefox (77.0.1) or Chrome (83). The following line did though:

&amp;&amp; Array.from(o.previousElementSibling.previousElementSibling.querySelectorAll("input, textarea, select")).filter(function(el) {return el.hasAttribute("data-xsd2html2xml-filled")}).length == 0) {

I'm not a Javascript expert, but as far as I can tell this should do the same as your suggestion, but only this works on my machine. Can you try the line above?

I'm using Python (lxml) to generate my HTML and viewing it locally as a file (rather than from a webserver).

If my suggestion works, maybe one of us should propose it as a merge?

@simonsirak
Copy link

Thanks for your response! I seem to have mistyped the anonymous function, the curly brackets in my line should be omitted (that's what my actual code looks like, I just couldn't copy paste it over at the time). But yours worked on mine as well 👍

I still think this is more of a workaround that fixes the problem without restructuring the population pipeline, and believe that a more thorough investigation of how to incorporate xs:choice into the pipeline should be done before submitting a Pull Request! But I think it is still good that this has been brought up here :)

Let's wait for the repository owner to learn what the next steps should be!

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

No branches or pull requests

3 participants