2

I have a model which is in XML format as shown below and I need to parse the XML and check whether my XML has internal-flag flag set as true or not. In my other models, it might be possible, that internal-flag flag is set as false. And sometimes, it is also possible that this field won't be there so by default it will be false from my code.

<?xml version="1.0"?>
<ClientMetadata
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://www.google.com client.xsd" 
 xmlns="http://www.google.com"> 
    <client id="200" version="13">
        <name>hello world</name>
        <description>hello hello</description>
        <organization>TESTER</organization>
        <author>david</author>
        <internal-flag>true</internal-flag>
        <clock>
            <clock>
                <for>
                    <init>val(tmp1) = 1</init>
                    <clock>
                        <eval><![CDATA[result("," + $convert(val(tmp1)))]]></eval>
                    </clock>
                </for>
                <for>
                    <incr>val(tmp1) -= 1</incr>
                    <clock>
                        <eval><![CDATA[result("," + $convert(val(tmp1)))]]></eval>
                    </clock>
                </for>
            </clock>
        </clock>
    </client>
</ClientMetadata>

I have a POJO in which I am storing my above model -

public class ModelMetadata {

    private int modelId;
    private String modelValue; // this string will have my above XML data as string

    // setters and getters here

}

Now what is the best way to determine whether my model has internal-flag set as true or not?

// this list will have all my Models stored
List<ModelMetadata> metadata = getModelMetadata();

for (ModelMetadata model : metadata) {
    // my model will be stored in below variable in XML format
    String modelValue = model.getModelValue();

    // now parse modelValue variable and extract `internal-flag` field property
}

Do I need to use XML parsing for this or is there any better way to do this?

Update:-

I have started using Stax and this is what I have tried so far but not sure how can I extract that field -

InputStream is = new ByteArrayInputStream(modelValue.getBytes());

XMLStreamReader r = XMLInputFactory.newInstance().createXMLStreamReader(is);
while(r.hasNext()) {
    // now what should I do here?
}
john
  • 11,311
  • 40
  • 131
  • 251
  • How does your bean get populated from the XML? How do you get all the other fields (such as "name")? – Thilo Jan 06 '15 at 04:06
  • @Thilo, as of now I am not doing anything with XML. In my `ModelMetadata` class, there is a variable called `modelValue` - this variable is storing my XML in string format as it is so that means I need to use `String modelValue = model.getModelValue();` to do the XML parsing. – john Jan 06 '15 at 04:07
  • For XML parsing options, see this http://stackoverflow.com/questions/23509480/how-to-extract-values-from-below-xml-code-using-java?rq=1 – Thilo Jan 06 '15 at 04:27
  • @Thilo I started using Stax to parse my XML but got stuck. I have updated the question with the code I have. – john Jan 06 '15 at 04:45

3 Answers3

4

There is an easy solution using XMLBeam (Disclosure: I'm affiliated with that project), just a few lines:

public class ReadBoolean {
    public interface ClientMetaData {
        @XBRead("//xbdefaultns:internal-flag")
        boolean hasFlag();
    }
    public static void main(String[] args) throws IOException {
      ClientMetaData clientMetaData = new XBProjector().io().url("res://xmlWithBoolean.xml").read(ClientMetaData.class);      
      System.out.println("Has flag:"+clientMetaData.hasFlag());
    }
}

This program prints out

Has flag:true

for your XML.

Cfx
  • 2,272
  • 2
  • 15
  • 21
0

You could also do some simple string parsing, but this will only work for small cases with proper XML and if there's only a single <internal-flag> element.

This is a simple solution to your problem without using any XML parsing utilities. Other solutions may be more robust or powerful.

  1. Find the index of the string literal <internal-flag>. If it doesn't exist, return false.
  2. Go forward "<internal-flag>".length (15) characters. Read up to the next </internal-flag>, which should be the string true or false.
  3. Take that string, use Boolean.parseBoolean(String) to get a boolean value.

If you want me to help you out with the code just drop a comment!

Anubian Noob
  • 13,426
  • 6
  • 53
  • 75
  • I don't think that's a good idea. Even when you have complete control over the XML generation. Things like XPath are not that difficult to use. – Thilo Jan 06 '15 at 04:08
  • String parsing xml is never a good advice. You need to take care of encoding and make sure that the search string is not commented out and more stuff. In the end you end up writing an XML parser yourself. And that is a bad idea. – Cfx Jan 06 '15 at 06:38
0

If you are willing to consider adding Groovy to your mix (e.g. see the book Making Java Groovy) then using a Groovy XMLParser and associated classes will make this simple.

If you need to stick to Java, let me put in a shameless plug for my Xen library, which mimics a lot of the "Groovy way". The answer to your question would be:

Xen doc = new XenParser().parseText(YOUR_XML_STRING);
String internalFlag = doc.getText(".client.internal-flag");
boolean isSet = "true".equals(internalFlag);

If the XML comes from a File, Stream, or URI, that can be handled too.

Caveat emptor, (even though it is free) this is a fairly new library, written solely by a random person (me), and not thoroughly tested on all the crazy XML out there. If anybody knows of a similar, more "mainstream" library I'd be very interested in hearing about it.

user949300
  • 15,364
  • 7
  • 35
  • 66