And I want to untie it with a JA...">

How to make JAXB unmarshaller ignore prefixes?

I have the following XML:

<ns2:Person name="John" age="20" /> 

And I want to untie it with a JAXB Person object that was generated from XSD.

this is the code I'm running:

 JAXBContext context = JAXBContext.newInstance(PersoEntity.class); Unmarshaller um = context.createUnmarshaller(); StringReader sr = new StringReader(xml); Person p = (Person)um.unmarshal(sr); 

Surprisingly, I get the following exception:

 javax.xml.bind.UnmarshalException - with linked exception: [org.xml.sax.SAXParseException: The prefix "ns2" for element "ns2:Person" is not bound.] 

How do I solve it? Thanks

+4
source share
2 answers

OBTAINING FRAGMENTS

The way you are currently retrieving an XML snippet causes namespace declarations to get lost. In your snippet, ns2 no longer a prefix, you just have the element name with a colon in it ( ns2:Person ). This will cause problems with parsers that support the namespace. The following article can help you get an XML snippet:

HANDLING CASE OF USE

Using the XML fragment that you have, you can create an XMLFilter that removes the prefix from the XML element and then uses the JAXB UnmarshallerHandler to do unmarshalling.

Demo

 package forum11968399; import java.io.StringReader; import javax.xml.bind.*; import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.XMLFilterImpl; public class Demo { private static final String xml = "<ns2:Person name='John' age='20' />"; public static void main(String[] args) throws Exception { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xmlReader = sp.getXMLReader(); XMLFilter xmlFilter = new MyXMLFilter(xmlReader); JAXBContext context = JAXBContext.newInstance(PersonEntity.class); Unmarshaller um = context.createUnmarshaller(); UnmarshallerHandler unmarshallerHandler = um.getUnmarshallerHandler(); xmlFilter.setContentHandler(unmarshallerHandler); StringReader sr = new StringReader(xml); xmlFilter.parse(new InputSource(sr)); PersonEntity p = (PersonEntity) unmarshallerHandler.getResult(); } private static class MyXMLFilter extends XMLFilterImpl { public MyXMLFilter(XMLReader xmlReader) { super(xmlReader); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { int colonIndex = qName.indexOf(':'); if(colonIndex >= 0) { qName = qName.substring(colonIndex + 1); } uri = XML_NAMESPACE; //to prevent unknown XML element exception, we have to specify the namespace here super.startElement(uri, localName, qName, attributes); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { int colonIndex = qName.indexOf(':'); if(colonIndex >= 0) { qName = qName.substring(colonIndex + 1); } super.endElement(uri, localName, qName); } } } 

Personentity

 package forum11968399; import javax.xml.bind.annotation.*; @XmlRootElement(name="Person") @XmlAccessorType(XmlAccessType.FIELD) public class PersonEntity { @XmlAttribute private String name; @XmlAttribute private int age; } 
+6
source

It is best, perhaps, to nest the element you want in another element that binds the namespace. It doesn't really matter what you are binding to, just make it a valid XML document that will parse. Then you can unmarshal declared type

 JAXBContext context = JAXBContext.newInstance(Person.class); Unmarshaller um = context.createUnmarshaller(); String xml = "<ns2:Person name=\"John\" age=\"20\" />"; String xmlWithPrefixMapped = "<ns2:FakeElement xmlns:ns2=\"someuri\">" + xml + "</ns2:FakeElement>"; StringReader sr = new StringReader(xmlWithPrefixMapped); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new InputSource(sr)); Node n = (Node) doc.getDocumentElement().getFirstChild(); JAXBElement<Person> personElement = um.unmarshal(n, Person.class); Person p = personElement.getValue(); 
+1
source

All Articles