3

I have the below class. When Marshalling, I would like to omit the tag "config", is it possible?

@XmlRootElement(name = "config")
@XmlAccessorType(XmlAccessType.FIELD)
public static class Config {

        @XmlElement(name = "dry-run")
        protected Boolean dryRun;

        @XmlElementWrapper(name = "filters")
        @XmlElement(name = "filter")
        protected List<String> filters;

        public Boolean isDryRun() {
                return dryRun;
        }

        public void setDryRun(boolean dryRun) {
                this.dryRun = dryRun;
        }

        public List<String> getFilters() {
                return filters;
        }
}

Example:

Current output:

<Root>
  <config xmlns:wf="nspace">
    <dry-run>false</dry-run>
    <filters>
      <filter>
        myFilter
      </filter>
    </filters>
  </config>
</Root>

Desired output:

<Root>
    <dry-run>false</dry-run>
    <filters>
      <filter>
        myFilter
      </filter>
    </filters>
</Root>

UPDATE:

all I wanted to know is "can it be done ONLY with JAXB or not?". Just check this question (not the answer), I didn't get how he marshelled with only JAXB and no root element was written. It is precisely what I want.

Adel Boutros
  • 10,205
  • 7
  • 55
  • 89
  • What type of output are you marshalling to (`OutputStream`, `StreamWriter`, `Node`, etc)? Also where does `Root` element come from in this use case. – bdoughan Feb 06 '13 at 10:58
  • Might be helpful - http://stackoverflow.com/q/12244479/1135954 – mtk Feb 06 '13 at 11:02
  • @BlaiseDoughan When marshalling the config, I get an xmlString. This string is appended in the Root element using Sax. It is due to legacy code which I cannot modify. – Adel Boutros Feb 06 '13 at 11:18
  • @mtk Thank you for the hint, but I cannot set the title to null because in some cases the tag "config" is required and in some cases (like the one in my answer, it isn't) – Adel Boutros Feb 06 '13 at 11:19

1 Answers1

0

So you want to marshal your object not to a single XML subtree, but to an XML fragment, i.e. a list of siblings without a parent. I believe there is no way to achieve this with Jaxb itself. But you can serialize to some intermediate form and process that. For example, you could create your own SAX ContentHandler and have that handler count depth and only delegate events at non-zero nesting depth.

class NoRoot extends XMLFilterImpl {

  private int depth;

  @Override public void startDocument() throws SAXException
  {
    depth = 0;
  }

  @Override public void startElement(String uri, String localName,
                                     String qName, Attributes atts)
    throws SAXException
  {
    if (depth != 0) super.startElement(uri, localName, qName, atts);
    ++depth;
  }

  @Override public void endElement(String uri, String localName,
                                   String qName)
    throws SAXException
  {
    --depth;
    if (depth != 0) super.endElement(uri, localName, qName);
  }

}
MvG
  • 57,380
  • 22
  • 148
  • 276
  • I know I can use SAX but we are migrating from SAX to JAXB so we don't want to use SAX again .. :( – Adel Boutros Feb 06 '13 at 19:08
  • @AdelBoutros: If you can't control the code which serializes the `Root` element, and also can't change the XMl schema, then you are running out of options. You can use DOM or STAX instead of SAX, but the net effect would be the same, plus you'd have one more API in your code. JAXB expects a close match between XML schema and Java objects, so unless someone else has a solution I overlooked, your setup does not match that expectation. – MvG Feb 06 '13 at 21:52
  • all I wanted to know is "can it be done ONLY with JAXB or not?". Just check this [link](http://www.coderanch.com/t/129773/XML/Marshalling-JAXB-Parent-tag), I didn't get how he marshelled with only JAXB and no root element was written. It is precisely what I want. – Adel Boutros Feb 06 '13 at 22:03
  • @AdelBoutros: The link you point out is from 2008. I guess JAXB was less strict in those days. As the link only specifies the XSD, I guess he generated java classes from that using xjc. In that case, the class he marshalled would have been annotated using `@XmlType` but not `@XmlRootElement`. But when I try to reproduce this with a recent version of Java, I get a MarshalException: “unable to marshal type "generated.CustomerType" as an element because it is missing an `@XmlRootElement` annotation”. So this might have worked at some point, but it appears to no longer work today. – MvG Feb 07 '13 at 07:06