Alireza Fattahi
Alireza Fattahi

Reputation: 45553

Check xml elements business rules directly with xpath or convert them to java object

In a java project, consider a file with about 1,000-100,000 xml elements in it. Each xml element needs to be validated with some business rules.

Some of the element nodes are as below:

<transfer>
  <bank-id>BIESXXTH</bank-id>
  <from-account>016534412</from-account>
  <to-account>016534412</to-account>
  <amount>765000</amount>
  <transaction-time>2015-08-08T13:34:00</transaction-time>
</transfer>

The rules are some thing like:

The size of xml file with 1,000 elements is about 400KB and the size of file with 100,000 elements the file size will be about 40MB

To validate the business rules we can:

I want to know, which one is better (considering performance and memory usage)?!

Also if any one has same experience, may it come the situation that I could not do what I want with xpath !

Upvotes: 2

Views: 373

Answers (2)

zakaiter
zakaiter

Reputation: 439

For dynamic xpath to object implementation you can have a look into this.

Example 1: JavaBean Property Access

JXPath can be used to access properties of a JavaBean.

 public class Employee {
    public String getFirstName(){
       ...
    }
 }

 Employee emp = new Employee();
 JXPathContext context = JXPathContext.newContext(emp);
 String fName = (String)context.getValue("firstName");

In this example, we are using JXPath to access a property of the emp bean. In this simple case the invocation of JXPath is equivalent to invocation of getFirstName() on the bean.

Example 2: Nested Bean Property Access

JXPath can traverse object graphs:

 public class Employee {
    public Address getHomeAddress(){
       ...
    }
 }
 public class Address {
    public String getStreetNumber(){
       ...
    }
 }

 Employee emp = new Employee();
 ...

 JXPathContext context = JXPathContext.newContext(emp);
 String sNumber = (String)context.getValue("homeAddress/streetNumber");

In this case XPath is used to access a property of a nested bean. A property identified by the xpath does not have to be a "leaf" property. For instance, we can extract the whole Address object in above example:

Address addr = (Address)context.getValue("homeAddress");

Example 3: Setting Properties

JXPath can be used to modify property values.

 public class Employee {
    public Address getAddress() {
       ...
    }

    public void setAddress(Address address) {
       ...
    }
 }

 Employee emp = new Employee();
 Address addr = new Address();
 ...

 JXPathContext context = JXPathContext.newContext(emp);
 context.setValue("address", addr);
 context.setValue("address/zipCode", "90190");

Example 4: Creating objects JXPath can be used to create new objects. First, create a subclass of AbstractFactory and install it on the JXPathContext. Then call createPathAndSetValue() instead of "setValue". JXPathContext will invoke your AbstractFactory when it discovers that an intermediate node of the path is null. It will not override existing nodes.

public class AddressFactory extends AbstractFactory {
    public boolean createObject(JXPathContext context,
               Pointer pointer, Object parent, String name, int index){
     if ((parent instanceof Employee) && name.equals("address"){
       ((Employee)parent).setAddress(new Address());
       return true;
     }
     return false;
   }
 }

 JXPathContext context = JXPathContext.newContext(emp);
 context.setFactory(new AddressFactory());
 context.createPathAndSetValue("address/zipCode", "90190");

Upvotes: 1

McNultyyy
McNultyyy

Reputation: 1032

File xmlFile = new File(path);

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(
    "http://apache.org/xml/features/nonvalidating/load-external-dtd",
    false);
DocumentBuilder builder = factory.newDocumentBuilder();

document = builder.parse(xmlFile); //or parse the String
document.getDocumentElement().normalize();

So now you have the xml file as a Document object.

I'd suggest checking each node as it comes up so you don't have to create objects that potentially won't be added to the list.

List<Transfer> list = new ArrayList<Transfer>();
NodeList nodelist = document.getElementsByTagName("transfer");

for (int i=0; i<nodelist.getLength(); i++) {
    Element element = (Element) nodelist.item(i);

    if (isValidTransfer(element) {
        Transfer t = buildTransferFromElement(element);
        list.add(t);
    }
}

I'm sure you can work out how to create the isValidTransfer and buildTransferFromElement methods.

Give the W3C Javadoc a read as well, it's pretty helpful.

Upvotes: 1

Related Questions