35313

reordering XML tags

Question:

I am trying to implement something which is for writing back the content tree of java object to XML file (object marshalling) (I know there are a lot of APIs for doing that but its required from me), I want to let the user to reorder the tags as he/she wants, I know using annotation like what JAXB has may solve that, but I think using annotation may cause a lot of pain. it will be so helpful if any one could offer any good approach.

Thanks

Answer1:

<strong>Note:</strong> I'm the <strong><a href="http://www.eclipse.org/eclipselink/moxy.php" rel="nofollow">EclipseLink JAXB (MOXy)</a></strong> lead and a member of the <a href="http://jcp.org/en/jsr/detail?id=222" rel="nofollow"><strong>JAXB (JSR-222)</strong></a> expert group.

In <a href="https://stackoverflow.com/a/11218017/383861" rel="nofollow"><strong>another answer</strong></a> I described the standard JAXB mechanisms for specifying the order of elements. In this answer I will explain how MOXy's external mapping document can be used to address this part of your question:

<blockquote>

I want to let the user to reorder the tags as he/she wants, I know using annotation like what JAXB has may solve that, but I think using annotation may cause a lot of pain.

</blockquote>

<strong>Root</strong>

In the Root class I have used the @XmlType annotation to specify an ordering.

package forum11217734; import javax.xml.bind.annotation.*; @XmlRootElement @XmlType(propOrder={"c", "b", "a"}) public class Root { private String a; private String b; private String c; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public String getC() { return c; } public void setC(String c) { this.c = c; } }

<strong>jaxb.properties</strong>

To specify MOXy as your JAXB provider you need to add a file called jaxb.properties in the same package as your domain model with the following entry (see <a href="http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html" rel="nofollow">Specifying EclipseLink MOXy as Your JAXB Provider</a>):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

<strong>binding-acb.xml</strong>

MOXy has an external mapping document extension that allows you to override the mappings on the domain model (see <a href="http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html" rel="nofollow">Extending JAXB - Representing Metadata as XML</a>). We will use this document to specify another ordering.

<?xml version="1.0"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="forum11217734"> <java-types> <java-type name="Root"> <xml-type prop-order="a c b"/> </java-type> </java-types> </xml-bindings>

<strong>binding-cab.xml</strong>

We can use additional mapping documents to provide alternate orderings.

<?xml version="1.0"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="forum11217734"> <java-types> <java-type name="Root"> <xml-type prop-order="c a b"/> </java-type> </java-types> </xml-bindings>

<strong>Demo</strong>

The following demo code demonstrates how to leverage the external mapping document when creating a JAXBContext. We will marshal the same instance of Root three different ways.

package forum11217734; import java.util.*; import javax.xml.bind.*; import org.eclipse.persistence.jaxb.JAXBContextFactory; public class Demo { public static void main(String[] args) throws Exception { Root root = new Root(); root.setA("Foo"); root.setB("Bar"); root.setC("Baz"); // CBA JAXBContext cbaContext = JAXBContext.newInstance(Root.class); Marshaller cbaMarshaller = cbaContext.createMarshaller(); cbaMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); cbaMarshaller.marshal(root, System.out); // ACB Map<String, Object> acbProperties = new HashMap<String, Object>(1); acbProperties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum11217734/binding-acb.xml"); JAXBContext acbContext = JAXBContext.newInstance(new Class[] {Root.class}, acbProperties); Marshaller acbMarshaller = acbContext.createMarshaller(); acbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); acbMarshaller.marshal(root, System.out); // CAB Map<String, Object> cabProperties = new HashMap<String, Object>(1); cabProperties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum11217734/binding-cab.xml"); JAXBContext cabContext = JAXBContext.newInstance(new Class[] {Root.class}, cabProperties); Marshaller cabMarshaller = cabContext.createMarshaller(); cabMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); cabMarshaller.marshal(root, System.out); } }

<strong>Output</strong>

Below is the output from running the demo code:

<?xml version="1.0" encoding="UTF-8"?> <root> <c>Baz</c> <b>Bar</b> <a>Foo</a> </root> <?xml version="1.0" encoding="UTF-8"?> <root> <a>Foo</a> <c>Baz</c> <b>Bar</b> </root> <?xml version="1.0" encoding="UTF-8"?> <root> <c>Baz</c> <a>Foo</a> <b>Bar</b> </root>

Answer2:

<a href="http://jcp.org/en/jsr/detail?id=222" rel="nofollow"><strong>JAXB (JSR-222)</strong></a> implementations provide a couple different mechanisms for specifying the order of XML elements when then content is marshalled to XML. JAXB does not require the elements be in order when unmarshalling.

<strong>OPTION #1 - @XmlType(propOrder={"c","b", "a"})</strong>

The propOrder property on the @XmlType annotation allows you to specify an order.

<em><strong>Root</strong></em>

package forum11217734; import javax.xml.bind.annotation.*; @XmlRootElement @XmlType(propOrder={"c","b", "a"}) public class Root { private String a; private String b; private String c; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public String getC() { return c; } public void setC(String c) { this.c = c; } }

<em><strong>Output</strong></em>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <root> <c>Baz</c> <b>Bar</b> <a>Foo</a> </root>

<em><strong>For More Information</strong></em>

<ul><li><a href="http://blog.bdoughan.com/2012/02/jaxbs-xmltype-and-proporder.html" rel="nofollow">http://blog.bdoughan.com/2012/02/jaxbs-xmltype-and-proporder.html</a></li> </ul>

<strong>OPTION #2 - @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)</strong>

You can also use the @XmlAccessorOrder annotation to specify that the properties should be marshalled in alphabetical order.

<em><strong>Root</strong></em>

package forum11217734; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) public class Root { private String a; private String b; private String c; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public String getC() { return c; } public void setC(String c) { this.c = c; } }

<em><strong>Output</strong></em>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <root> <a>Foo</a> <b>Bar</b> <c>Baz</c> </root>

<strong>DEMO CODE</strong>

The following demo code was used to produce the output for each of the options above.

package forum11217734; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Root root = new Root(); root.setA("Foo"); root.setB("Bar"); root.setC("Baz"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } }

Recommend

  • Return base class in C#
  • DeadLock in producer Consumer
  • Append values to a set in Python
  • Java downcasting and is-A has-A relationship
  • Upcasting and Overloading Stream Operator
  • Why is my serial communication not working?
  • Creating webservice (JAX-WS) with functions which return custom types
  • Writing Category Instance for custom Lens
  • execute a service after a call ajax in AngularJS
  • How to subtract two iterables in python
  • C++: Implicit Member Functions
  • Using EcliplseLink JPA how can I disable all the relationship lookups when persisting an object?
  • Read and Write within a file in C (double it)
  • How to use SpEL to inject result of method call in Spring?
  • Creating JS objects in PHP with commas in between
  • Dynamically set LESS variables from user settings
  • Relative paths. baseUrl and paths not working on ionic2 - angular2
  • PHP CURL timing out but CLI CURL works
  • With Hadoop, can I create a tasktracker on a machine that isn't running a datanode?
  • Deleting and Updating values from a cusrsor adapter
  • Is possible to count alias result on mysql
  • Importing jscolor library in angular 2
  • To display the title for the current loaction in map in iphone
  • Properly structure and highlight a GtkPopoverMenu using PyGObject
  • php design question - will a Helper help here?
  • KeystoneJS: Relationships in Admin UI not updating
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • JTable with a ScrollPane misbehaving
  • Angular 2 constructor injection vs direct access
  • Java static initializers and reflection
  • Android Google Maps API OnLocationChanged only called once
  • EntityFramework adding new object to nested object collection
  • Checking variable from a different class in C#
  • Django query for large number of relationships
  • Why is Django giving me: 'first_name' is an invalid keyword argument for this function?
  • How can I use `wmic` in a Windows PE script?
  • failed to connect to specific WiFi in android programmatically
  • UserPrincipal.Current returns apppool on IIS
  • How to push additional view controllers onto NavigationController but keep the TabBar?
  • How can I use threading to 'tick' a timer to be accessed by other threads?