Introduction
This is a simple app that shuffles elements in an XML file with respect to its XPath evaluation result. It uses XPath to address individual elements, then re-arranges and re-combines the fragments. Those fragments are identified by their offsets and lengths, both of which are obtained by calling VTDNav
's getElementFragment()
. Both C# and Java code are provided.
Why Not Use SAX or STaX?
Simply put, the lack of XPath support makes it very tedious, virtually impossible, for SAX or STaX to perform complex XML processing such as re-arranging XML element fragments in this example.
Why Not Use DOM?
Aside from well-known performance and memory usage problems, the redundant, wasteful de-serialization/serialization contributes nothing but overhead to the task.
The Code (Self Explanatory)
Input.xml
<root>
<a> text </a>
<b> text </b>
<c> text </c>
<a> text </a>
<b> text </b>
<c> text </c>
<a> text </a>
<b> text </b>
<c> text </c>
</root>
Output.xml
<root>
<a> text </a>
<a> text </a>
<a> text </a>
<b> text </b>
<b> text </b>
<b> text </b>
<c> text </c>
<c> text </c>
<c> text </c>
</root>
The C# code:
using System;
using com.ximpleware;
namespace shuffle
{
public class shuffle
{
public static void Main(String[] args)
{
VTDGen vg = new VTDGen();
AutoPilot ap0 = new AutoPilot();
AutoPilot ap1 = new AutoPilot();
AutoPilot ap2 = new AutoPilot();
ap0.selectXPath("/root/a");
ap1.selectXPath("/root/b");
ap2.selectXPath("/root/c");
Encoding eg = System.Text.Encoding.GetEncoding("utf-8");
if (vg.parseFile("old.xml", false))
{
VTDNav vn = vg.getNav();
ap0.bind(vn);
ap1.bind(vn);
ap2.bind(vn);
FileStream fos = new FileStream("new.xml",
System.IO.FileMode.OpenOrCreate);
byte[] ba0,ba1, ba2, ba3, ba4;
ba1 = eg.GetBytes("<root>");
ba2 = eg.GetBytes("</root>");
ba3 = eg.GetBytes("\n");
fos.Write(ba1, 0, ba1.Length);
byte[] ba = vn.getXML().getBytes();
while (ap0.evalXPath() != -1)
{
long l = vn.getElementFragment();
int offset = (int)l;
int len = (int)(l >> 32);
fos.Write(ba3,0,ba3.Length);
fos.Write(ba, offset, len);
}
ap0.resetXPath();
while (ap1.evalXPath() != -1)
{
long l = vn.getElementFragment();
int offset = (int)l;
int len = (int)(l >> 32);
fos.Write(ba3,0,ba3.Length);
fos.Write(ba, offset, len);
}
ap1.resetXPath();
while (ap2.evalXPath() != -1)
{
long l = vn.getElementFragment();
int offset = (int)l;
int len = (int)(l >> 32);
fos.Write(ba3,0,ba3.Length);
fos.Write(ba, offset, len);
}
ap2.resetXPath();
fos.Write(ba3,0,ba3.Length);
fos.Write(ba2,0,ba2.Length);
}
}
}
}
The Java code:
import com.ximpleware.*;
import java.io.*;
public class shuffle {
public static void main(String[] args) throws Exception {
VTDGen vg = new VTDGen();
AutoPilot ap0 = new AutoPilot();
AutoPilot ap1 = new AutoPilot();
AutoPilot ap2 = new AutoPilot();
ap0.selectXPath("/root/a");
ap1.selectXPath("/root/b");
ap2.selectXPath("/root/c");
if (vg.parseFile("old.xml",false)){
VTDNav vn = vg.getNav();
ap0.bind(vn);
ap1.bind(vn);
ap2.bind(vn);
FileOutputStream fos = new FileOutputStream("new.xml");
fos.write("<root>".getBytes());
byte[] ba = vn.getXML().getBytes();
while(ap0.evalXPath()!=-1){
long l= vn.getElementFragment();
int offset = (int)l;
int len = (int)(l>>32);
fos.write('\n');
fos.write(ba,offset, len);
}
ap0.resetXPath();
while(ap1.evalXPath()!=-1){
long l= vn.getElementFragment();
int offset = (int)l;
int len = (int)(l>>32);
fos.write('\n');
fos.write(ba,offset, len);
}
ap1.resetXPath();
while(ap2.evalXPath()!=-1){
long l= vn.getElementFragment();
int offset = (int)l;
int len = (int)(l>>32);
fos.write('\n');
fos.write(ba,offset, len);
}
ap2.resetXPath();
fos.write('\n');
fos.write("</root>".getBytes());
}
}
}