getodk/javarosa

Space between output elements should be respected

Opened this issue · 8 comments

Software versions

JavaRosa v2.17 and prior.

Problem description

Space between output elements as in <output value=" ../person/first_name "/> <output value=" ../person/last_name "/> is not respected. That is, if first_name has value "Foo", last_name has value "Bar" and the two output elements are in a label, the label is displayed as "FooBar" rather than "Foo Bar".

Steps to reproduce the problem

named-repeat.xml.zip

Expected behavior

Spaces should be respected.

  • Confirm non-breaking spaces are preserved, add a test
  • See whether Enketo preserves regular spaces
  • Investigate preserving regular spaces
  • Consider outputting non-breaking spaces from pyxform

It happens in kxml2 (where files are parsed). We can't fix it in javaorsa. I also doubt it's possible to fix it in kxml2 since the code has not been touched for 2 years.
I just confirmed that using &#160; works so maybe we can do that while converting forms to xml like we do with <> for example.
What do you think?

Hello @grzesiek2010, you have been unassigned from this issue because you have not updated this issue or any referenced pull requests for over 15 days.

You can reclaim this issue or claim any other issue by commenting @opendatakit-bot claim on that issue.

Thanks for your contributions, and hope to see you again soon!

@lognaturel I'm willing to give this one a try. I took a look at the code but don't know how to reproduce it. Is there a similar test I can duplicate and configure to use your attached xml file?

Thanks so much, @macdude357! I think that @grzesiek2010 is likely right but haven't had a chance for a sanity check. That said, spaces before and after outputs are respected so it seems it might be possible.

This is the kind of test I had in mind:

    @Test
    public void spacesBetweenOutputs_areRespected() throws IOException {
        Scenario scenario = Scenario.init("spaces-outputs", html(
            head(
                model(
                    mainInstance(t("data id=\"spaces-outputs\"",
                        t("first_name"),
                        t("last_name"),
                        t("question")
                    )),
                    bind("/data/question").type("string")
                )),
            body(
                input("/data/question",
                    t("label", "Full name: <output value=\" ../first_name \"/>           <output value=\" ../last_name \"/>"))
            )
        ));

        scenario.next();
        assertThat(scenario.getQuestionAtIndex().getLabelInnerText(), is("Full name: ${0} ${1}"));
    }

You can see that if you add spaces after "Full name:" those will go through. But all space between the tags is collapsed.

The expected output with ${0} placeholders is odd but I think it's fine for this test because what we care about is truly the template structure. Those templates get replaced at FormEntryCaption.getQuestionText which we don't have access to in Scenario.

Even if the conclusion is that there's nothing non-invasive we can do about it, it'd be great to have a test with comment to document the limitation and why it's there.

After looking at the code, I'm not sure this is a good test. The code that generates the placeholders (${0} and ${1}) looks like this:
String s = "${" + parseOutput(kid) + "}";
The spacing is part of "kid" so at the very least, it might be more correct to expect ${ 0 } but I don't think that's correct either. Either that, or the code would have to check for leading/trailing space in kid, then add that to the String s above but that seems kind of a hack. I'll keep looking but if you happen to have any more hints, they are more than welcome.

First, I hope you're well and thanks for coming back to this!

I haven't looked at the code in a bit but doesn't either parseOutput or some previous step that produces kid take care of white space around the reference in an output? That whitespace isn't meaningful so I think it's doing the right thing. It's the space between two output tags that's meaningful.

Really, the assert in my test should be

"Full name: ${0}           ${1}"

I see. I thought that the spacing around ../first_name was the issue but it's the spacing between the tags that needs to be maintained. Thanks for clarifying.

I found that putting a non-breaking space between the output elements results in the desired behavior:
"Full name: <output value=\" ../first_name \"/>\u00A0<output value=\" ../last_name \"/>
The result is that ${0} and ${1} have a nbsp between them. So long as whatever consumes that honors that nbsp then that should work. @lognaturel