There are a few items that are tripping you up:
ISSUE #1 - ContentRoot Contains Invalid Mappings
EclipseLink JAXB (MOXy) does not allow the following combination of mappings. With the second xml-element you are telling MOXy to map the contents properties to the repeating element b that occur within the element a. With the first xml-element you are trying to map the text attribute of one of the potentially many b elements to the String property text.
<java-type name="ContentRoot">
<java-attributes>
<xml-element java-attribute="text" xml-path="a/b/@text" />
<xml-element java-attribute="contents" xml-path="a/b" type="test.Content" container-type="java.util.List" />
</java-attributes>
</java-type>
The correct place to map the text attribute is on the Content class which you already had. Instead of using the xml-element mapping with the xml-path pointing at the attribute (which would work), I would recomment using the xml-attribute mapping and specifying a name.
<java-type name="Content">
<java-attributes>
<xml-attribute java-attribute="text"/>
</java-attributes>
</java-type>
ISSUE #2 - xml-path Is Not Properly Namespace Qualified
Since in bindings.xml you have associated the foo prefix with the http://www.domain.org/foo namespace URI.
<xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
<xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
</xml-schema>
When you specify the xml-path you need to include the prefix in order to get the correct namespace qualification.
<java-type name="ContentRoot">
<java-attributes>
<xml-element java-attribute="contents" xml-path="foo:a/foo:b"/>
</java-attributes>
</java-type>
For More Information
http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
Alternatively you could have mapped it with an xml-element-wrapper as follows:
<java-type name="ContentRoot">
<java-attributes>
<xml-element java-attribute="contents" name="b">
<xml-element-wrapper name="a"/>
</xml-element>
</java-attributes>
</java-type>
ISSUE #3 - xml-path="." Can Not Be Used on a Collection Property
Currently MOXy requires that each item in a collection correspond to its own element. This means that at this time you can not specify the self XPath . for collection properties.
Full Example
Your demo code didn't seem to fully match your domain model. Here is a complete example that pulls everything together:
Root
package test;
public class Root {
private ContentRoot contentRoot;
public ContentRoot getContentRoot() {
return contentRoot;
}
public void setContentRoot(ContentRoot contentRoot) {
this.contentRoot = contentRoot;
}
}
ContentRoot
package test;
import java.util.List;
public class ContentRoot {
private List<Content> contents;
public List<Content> getContents() {
return contents;
}
public void setContents(List<Content> contents) {
this.contents = contents;
}
}
Content
package test;
public class Content {
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
bindings.xml
<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="test"
xml-accessor-type="FIELD">
<xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
<xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
</xml-schema>
<java-types>
<java-type name="Root">
<xml-root-element/>
<java-attributes>
<xml-element java-attribute="contentRoot" xml-path="."/>
</java-attributes>
</java-type>
<java-type name="ContentRoot">
<java-attributes>
<xml-element java-attribute="contents" xml-path="foo:a/foo:b"/>
</java-attributes>
</java-type>
<java-type name="Content">
<java-attributes>
<xml-attribute java-attribute="text"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
Demo
package test;
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> jaxbContextProperties = new HashMap<String, Object>(1);
jaxbContextProperties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "test/bindings.xml");
JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {Root.class}, jaxbContextProperties);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Root root = (Root)unmarshaller.unmarshal(new File("src/test/input.xml"));
System.out.println(root.getContentRoot().getContents().get(0).getText());
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}