How to get multiple Substrings of the same Index?

Viewed 133

I want to extract every Area between <xsd:headerName> and </xsd:headerName>. Since I write a code generator I can't define how often it is present because it can be different with every xml.

I just get null pointers when executing so what do I do wrong?

Without the list I get the first area but I need all of them separately.

     String xmlToString = null;
     List<String> ComplexTypeList = null;
     String path = "/path/of/xml";
            try {
                xmlToString = FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8);

            } catch (IOException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < headerName.size(); i++) {

                String result = xmlToString.substring(xmlToString.indexOf("<xsd:headerName"), xmlToString.indexOf("</xsd:headerName>") + 18); // +18 so i get </xsd:headerName>
                ComplexTypeList.add(result); // here i get a Nullpointer
            }

EDIT: So now that it almost works I still have the problem that he always takes the same / first area. How can I solve this so that he always jumps to the next one?

3 Answers

You can use a regex instead of manually searching the String:

String str = "<xsd:headerName>  Hello</xsd:headerName><xsd:headerName>World</xsd:headerName><xsd:headerName> and </xsd:headerName>";
Matcher matcher = Pattern.compile("<xsd:headerName>[\\s\\S]*?</xsd:headerName>").matcher(str); // regex pattern

Before Java 9:

List<String> result = new ArrayList<>();
while(matcher.find()) {
    result.add(matcher.group());
}

After Java 9:

List<String> result = matcher.results().map(MatchResult::group).collect(Collectors.toList());

Printing the result:

result.forEach(System.out::println);

Output:

<xsd:headerName>  Hello</xsd:headerName>
<xsd:headerName>World</xsd:headerName>
<xsd:headerName> and </xsd:headerName>

You really don't want to be processing XML using string manipulation. You need a proper XML parser to turn into some data structure that you can then program against. Basically, if you do it by string handling then your code will inevitably fail against some legal inputs. That might not matter for a one-off ad-hoc process, but you specifically say that things "can be different with every xml", so you clearly need something more robust.

My preferred approach is always to use an XML-specific language (XPath, XSLT, XQuery), but if you want to use Java, then parse the XML into a tree structure (I'd recommend JDOM2 or XOM, but many people continue to use the old-and-clunky DOM that comes with the JDK), and then navigate this tree structure.

Try to declare List as a:

List<String> ComplexTypeList = new ArrayList<String>();
Related