Parser fails to throw InvalidXml exception on XML with < and > in text
I use this to parse XML from JUnit files for Android UI tests. The ones that fail spit out in the XML a
I have no control how Android UI tests spit out JUnit. How do I have it parse out the failure string and ignore this issue of less than. I remember somehow being able to do this many years ago but haven't touched XML in ages.
Example test fail: It will parse in order the first 3 but the last two won't be seen and no error happens either...
<testcase name="saveAndUnsave" classname="SearchResultsRegressions" time="32.048"/>
<testcase name="NoCallButton" classname="SearchResultsRegressions" time="0.001">
<skipped/>
</testcase>
<testcase name="Call" classname="SearchResultsRegressions" time="30.647">
<failure>androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (Child at position 0 in parent (view.getId() is <2131363167/debug:id/row_button_container> and Child at position 15 in parent (view.getId() is <2131363339/debug:id/rpConstraintLayout> and Child at position 0 in parent view.getId() is 2131363162/debug:id/rp_container>))) View Hierarchy: +>DecorView{id=-1, visibility=VISIBLE, width=1080, height=1920, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) sim={adjust=pan} layoutInDisplayCutoutMode=shortEdges ty=BASE_APPLICATION wanim=0x10302fe fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS pfl=NO_MOVE_ANIMATION FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED bhv=DEFAULT fitSides=}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3} | +->LinearLayout{id=-1, visibility=VISIBLE, width=1080, height=1794, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@YYYYYY, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2} | +--</failure>
</testcase>
<testcase name="Splash_Displays" classname="SplashRegressions" time="0.002">
<skipped/>
</testcase>
<testcase name="DP_Refresh_Banner" classname="dpRegressions" time="0.002">
<skipped/>
</testcase>
The XML you are attempting to parse is invalid, so it can't be parsed. I don't know where you get the data from, but you should find the offending software and file a bug report.
For completeness, I tried to parse the data using XStream and Jackson. Both throw an exception on this input. I think that is correct behavior. Returning half the data seems particularly bad on my part. I'm going to fix this.
BTW you are probably not doing anything wrong in your code. This is what I used to parse the data:
private static final String DATA = """
<root>
<testcase name="saveAndUnsave" classname="SearchResultsRegressions" time="32.048"/>
<testcase name="NoCallButton" classname="SearchResultsRegressions" time="0.001">
<skipped/>
</testcase>
<testcase name="Call" classname="SearchResultsRegressions" time="30.647">
<failure>androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (Child at position 0 in parent (view.getId() is <2131363167/debug:id/row_button_container> and Child at position 15 in parent (view.getId() is <2131363339/debug:id/rpConstraintLayout> and Child at position 0 in parent view.getId() is 2131363162/debug:id/rp_container>))) View Hierarchy: +>DecorView{id=-1, visibility=VISIBLE, width=1080, height=1920, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) sim={adjust=pan} layoutInDisplayCutoutMode=shortEdges ty=BASE_APPLICATION wanim=0x10302fe fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS pfl=NO_MOVE_ANIMATION FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED bhv=DEFAULT fitSides=}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3} | +->LinearLayout{id=-1, visibility=VISIBLE, width=1080, height=1794, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@YYYYYY, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2} | +--</failure>
</testcase>
<testcase name="Splash_Displays" classname="SplashRegressions" time="0.002">
<skipped/>
</testcase>
<testcase name="DP_Refresh_Banner" classname="dpRegressions" time="0.002">
<skipped/>
</testcase>
</root>""";
public record Root(@XmlName("testcase") List<ParseInvalidXml.TestCase> testcases) {}
public record TestCase(
@XmlAttribute String name, @XmlAttribute String classname, @XmlAttribute String time,
String skipped, ParseInvalidXml.Failure failure) {}
public record Failure(@XmlTextNode String text) {}
public static void main(final String... args) {
final var xml = new XmlParser();
final var pojo = xml.fromXml(DATA, ParseInvalidXml.Root.class);
System.out.println(pojo.testcases.size());
System.out.println(pojo.testcases.get(2).name);
}
Well, it looks like something an HTML parser might accept (though even then the output would not look like you want it to), but yeah - it certainly is not valid XML
HTML parsers are a whole other thing. They generally accept all kinds of broken stuff. I haven't tested this myself, but you could try using JSoup to parse this. It returns a queryable Document, and it is far less likely to die with an error.
I released a new version (3.3.0). It should now properly die with an InvalidXml exception on the input you gave. This is the same behavior other XML parser have. @grndvl1 can you check this?