-1

I have following String (not a file but String variable) from which I need to create an Array or List of Strings with [x]ValueNeeded so I would end up having:

String[] array = {'firstValueNeeded', 'secondValueNeeded', [...], 'nthValueNeeded'}

This are the values of this piece of String: <SubTagColumn TagColumnId="777" TagColumnValue="firstValueNeeded" />

Note that the TagColumnID will always be '777'

I never know how long this String will be and how many elements it will have but I have to get all of them.

<MainTag>
   <MainTagRow PrimaryId="1234" Delete="false" >
      <MainTagColumn TagColumnId="1" TagColumnValue="1234" />
      <MainTagColumn TagColumnId="2" TagColumnValue="2345" />
      <MainTagColumn TagColumnId="3" TagColumnValue="Name" />
      <MainTagColumn TagColumnId="4" TagColumnValue="" />
      <MainTagColumn TagColumnId="5" TagColumnValue="someValue" />
      <MainTagColumn TagColumnId="6" TagColumnValue="654" />
      <MainTagColumn TagColumnId="7" TagColumnValue="" />
      <MainTagColumn TagColumnId="8" TagColumnValue="1" />
      <SubTag TagId="123">
         <SubTagRow PrimaryId="-1" Delete="true">
            <SubTagColumn TagColumnId="123" TagColumnValue="" />
            <SubTagColumn TagColumnId="234" TagColumnValue="" />
            <SubTagColumn TagColumnId="777" TagColumnValue="firstValueNeeded" />
         </SubTagRow>
         <SubTagRow PrimaryId="-2" Delete="true">
            <SubTagColumn TagColumnId="543" TagColumnValue="" />
            <SubTagColumn TagColumnId="432" TagColumnValue="" />
            <SubTagColumn TagColumnId="777" TagColumnValue="secondValueNeeded" />
         </SubTagRow>
...
         <SubTagRow PrimaryId="-2" Delete="true">
            <SubTagColumn TagColumnId="543" TagColumnValue="" />
            <SubTagColumn TagColumnId="432" TagColumnValue="" />
            <SubTagColumn TagColumnId="777" TagColumnValue="nthValueNeeded" />
         </SubTagRow>
      </SubTag>
   </MainTagRow>
</MainTag>

How can I achive this using Java 1.7?

Ryszard Czech
  • 18,032
  • 4
  • 24
  • 37
Lenny
  • 887
  • 1
  • 11
  • 32

3 Answers3

2

Using tools designed for XML might require some new skills, but it will save you from patching over a thousand tiny corner cases that crop up over time when you don't confront XML directly.

In this case, you can compile an expression that fetches what you need from the document. This is analogous to compiling a regex, and will be more efficient if you are applying the pattern to many documents.

XPathFactory f = XPathFactory.newInstance();
XPath xpath = f.newXPath();
XPathExpression expr =
    xpath.compile("//SubTagColumn[@TagColumnId='777']/@TagColumnValue");

Here, I'm matching a SubTagColumn element regardless of its ancestry. If you want to be more specific, you can add elements to the path. This expression says, "Find SubTagColumn elements with a TagColumnId of 777, and extract the TagColumnValue attribute."

Then, assuming the string doc contains the XML data, you can extract the values you need:

/* Adapt your string to an input source. */
InputSource source = new InputSource(new StringReader(doc));
/* Evaluate the previously compiled expression against your input. */
NodeList nodes = (NodeList) expr.evaluate(source, XPathConstants.NODESET);
/* Now use the results... */
for (int idx = 0; idx < nodes.getLength(); ++idx) {
    System.out.println(((Attr) nodes.item(idx)).getValue());
}

This step can be performed repeatedly against many documents, just like you could apply the same Pattern to many inputs using regular expressions.

If you don't require the XML to be a String for some other purpose, I would avoid it. You can create an InputSource from an InputStream directly, and that can be more efficient, as well as avoiding character encoding problems and other issues.

erickson
  • 265,237
  • 58
  • 395
  • 493
0

String processing (i.e. substring or regex) is arguably not appropriate here. Since it is XML, you should use an XML parser.

Here is a link to a Stack Overflow question and answer about parsing similar data with Java and XPath: How to read XML using XPath in Java

GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
0

You can use a SAX parser to accomplish your task. Refer to Parsing an XML File Using SAX

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class XmlParse extends DefaultHandler {
    private List<String> values;

    public XmlParse() {
        values = new ArrayList<String>();
    }

    public static void main(String[] args) {
        String xml = 
"<MainTag>" +
   "<MainTagRow PrimaryId=\"1234\" Delete=\"false\" >" +
      "<MainTagColumn TagColumnId=\"1\" TagColumnValue=\"1234\" />" +
      "<MainTagColumn TagColumnId=\"2\" TagColumnValue=\"2345\" />" +
      "<MainTagColumn TagColumnId=\"3\" TagColumnValue=\"Name\" />" +
      "<MainTagColumn TagColumnId=\"4\" TagColumnValue=\"\" />" +
      "<MainTagColumn TagColumnId=\"5\" TagColumnValue=\"someValue\" />" +
      "<MainTagColumn TagColumnId=\"6\" TagColumnValue=\"654\" />" +
      "<MainTagColumn TagColumnId=\"7\" TagColumnValue=\"\" />" +
      "<MainTagColumn TagColumnId=\"8\" TagColumnValue=\"1\" />" +
      "<SubTag TagId=\"123\">" +
         "<SubTagRow PrimaryId=\"-1\" Delete=\"true\">" +
            "<SubTagColumn TagColumnId=\"123\" TagColumnValue=\"\" />" +
            "<SubTagColumn TagColumnId=\"234\" TagColumnValue=\"\" />" +
            "<SubTagColumn TagColumnId=\"777\" TagColumnValue=\"firstValueNeeded\" />" +
         "</SubTagRow>" +
         "<SubTagRow PrimaryId=\"-2\" Delete=\"true\">" +
            "<SubTagColumn TagColumnId=\"543\" TagColumnValue=\"\" />" +
            "<SubTagColumn TagColumnId=\"432\" TagColumnValue=\"\" />" +
            "<SubTagColumn TagColumnId=\"777\" TagColumnValue=\"secondValueNeeded\" />" +
         "</SubTagRow>" +
         "<SubTagRow PrimaryId=\"-2\" Delete=\"true\">" +
            "<SubTagColumn TagColumnId=\"543\" TagColumnValue=\"\" />" +
            "<SubTagColumn TagColumnId=\"432\" TagColumnValue=\"\" />" +
            "<SubTagColumn TagColumnId=\"777\" TagColumnValue=\"nthValueNeeded\" />" +
         "</SubTagRow>" +
      "</SubTag>" +
   "</MainTagRow>" +
"</MainTag>";
        SAXParserFactory spf = SAXParserFactory.newInstance();
        try {
            SAXParser saxParser = spf.newSAXParser();
            XMLReader xmlReader = saxParser.getXMLReader();
            XmlParse me = new XmlParse();
            xmlReader.setContentHandler(me);
            StringReader sr = new StringReader(xml);
            InputSource input = new InputSource(sr);
            xmlReader.parse(input);
            \\ 'values' now contains all required values that were extracted from XML.
        }
        catch (IOException | ParserConfigurationException | SAXException x) {
            x.printStackTrace();
        }
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        if ("SubTagColumn".equals(qName)) {
            int len = atts.getLength();
            if (len >= 2) {
                if ("TagColumnId".equals(atts.getQName(0))) {
                    if ("777".equals(atts.getValue(0))) {
                        String val = atts.getValue(1);
                        values.add(val);
                    }
                }
            }
        }
    }
}
Abra
  • 19,142
  • 7
  • 29
  • 41