2012-08-15 132 views
4

我有以下XML:如何让JAXB unmarshaller忽略前缀?

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

我想将它解组到从XSD生成的JAXB对象的人。

这是代码,我跑:

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

令人惊讶的,我得到以下异常:

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

如何解决这个问题呢?谢谢

+1

你只发布一个XML标签......这真的是你的情况,即你要来解读眼前这个段(或者有一个完整的xml文档,应该有xmlns:ns2定义)? – Less 2012-08-15 11:28:46

+0

你猜对了,只有这个片段是我想要的 – 2012-08-15 13:05:10

回答

6

抵达片段

您目前得到的XML片段导致丢失的命名空间声明的方式。在你的片段中ns2不再是一个前缀,你只需要一个带冒号的元素名称(ns2:Person)。这会导致命名空间感知解析器出现问题。下面的文章可能是一个更好的办法,你得到的XML片段:

处理您的使用例

使用,你有XML片段,您可以创建一个XMLFilter,它从XML元素中删除前缀,然后利用JAXB的UnmarshallerHandler进行解组。

演示

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; 

} 
+0

你的解决方案几乎奏效。我不得不修改一下。尽管我们删除了前缀,但由于名称空间问题,我仍然遇到了未知XML元素的异常。所以我只是把名字空间放在Uri变量中,它工作:) – 2012-08-17 09:18:15

1

最好的办法是将所需的元素嵌套到另一个绑定命名空间的元素中。将它绑定到什么并不重要,只要将其制作为有效的XML文档即可解析。然后你可以unmarshal by 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(); 
+0

我得到以下内容: Unmarshaller类型中unmarshal(Node,Class )方法不适用于参数(Element,Class ) – 2012-08-15 12:59:02

+0

这适用于我,尽管不是将它嵌套到一个新元素中,但我只是将名称空间信息添加到了我所获得的顶级标记中。 – 2015-11-05 14:19:07