不带 @XMLRootElement 的 JAXB 部分解组元素

发布于 2024-11-17 00:19:05 字数 10236 浏览 6 评论 0原文

我正在使用 JAXBpartial-unmarshalling 示例,但我无法解组不在根级别的 XML 元素(因为它们没有@XmlRootElement 标记)。在我的示例中,我尝试读取shipTo-Element而不是purchaseOrder-Element。

通常我会使用 JAXBElement unmarshal(Source source,ClassclarifiedType) 但由于该示例使用 UnmarshallerHandler 和 XMLFilterImpl 我不知道在哪里告诉 Jaxb 它应该使用哪个类。

我的错误消息是:引起:javax.xml.bind.UnmarshalException:意外元素(uri:“”,本地:“shipTo”)。预期元素为 <{}comment>、<{}purchaseOrder>、<{}purchaseOrders>

我用谷歌搜索了很多,但还没有找到任何有用的东西。

以下是 JaxB-Webpage 中的示例代码:

Main.java

public class Main {
public static void main( String[] args ) throws Exception {

    // create JAXBContext for the primer.xsd
    JAXBContext context = JAXBContext.newInstance("primer");

    // create a new XML parser
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setNamespaceAware(true);
    XMLReader reader = factory.newSAXParser().getXMLReader();

    // prepare a Splitter
    Splitter splitter = new Splitter(context);

    // connect two components
    reader.setContentHandler(splitter);

    for( int i=0; i<args.length; i++ ) {
        // parse all the documents specified via the command line.
        // note that XMLReader expects an URL, not a file name.
        // so we need conversion.
        reader.parse(new File(args[i]).toURL().toExternalForm());
    }
}

}

Splitter.java

public class Splitter extends XMLFilterImpl {

public Splitter( JAXBContext context ) {
    this.context = context;
}

/**
 * We will create unmarshallers from this context.
 */
private final JAXBContext context;


public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
    throws SAXException {

    if( depth!= 0 ) {
        // we are in the middle of forwarding events.
        // continue to do so.
        depth++;
        super.startElement(namespaceURI, localName, qName, atts);
        return;
    }

    if( namespaceURI.equals("") && localName.equals("purchaseOrder") ) {
        // start a new unmarshaller
        Unmarshaller unmarshaller;
        try {
            unmarshaller = context.createUnmarshaller();
        } catch( JAXBException e ) {
            // there's no way to recover from this error.
            // we will abort the processing.
            throw new SAXException(e);
        }
        unmarshallerHandler = unmarshaller.getUnmarshallerHandler();

        // set it as the content handler so that it will receive
        // SAX events from now on.
        setContentHandler(unmarshallerHandler);

        // fire SAX events to emulate the start of a new document.
        unmarshallerHandler.startDocument();
        unmarshallerHandler.setDocumentLocator(locator);

        Enumeration e = namespaces.getPrefixes();
        while( e.hasMoreElements() ) {
            String prefix = (String)e.nextElement();
            String uri = namespaces.getURI(prefix);

            unmarshallerHandler.startPrefixMapping(prefix,uri);
        }
        String defaultURI = namespaces.getURI("");
        if( defaultURI!=null )
            unmarshallerHandler.startPrefixMapping("",defaultURI);

        super.startElement(namespaceURI, localName, qName, atts);

        // count the depth of elements and we will know when to stop.
        depth=1;
    }
}

public void endElement(String namespaceURI, String localName, String qName) throws SAXException {

    // forward this event
    super.endElement(namespaceURI, localName, qName);

    if( depth!=0 ) {
        depth--;
        if( depth==0 ) {
            // just finished sending one chunk.

            // emulate the end of a document.
            Enumeration e = namespaces.getPrefixes();
            while( e.hasMoreElements() ) {
                String prefix = (String)e.nextElement();
                unmarshallerHandler.endPrefixMapping(prefix);
            }
            String defaultURI = namespaces.getURI("");
            if( defaultURI!=null )
                unmarshallerHandler.endPrefixMapping("");
            unmarshallerHandler.endDocument();

            // stop forwarding events by setting a dummy handler.
            // XMLFilter doesn't accept null, so we have to give it something,
            // hence a DefaultHandler, which does nothing.
            setContentHandler(new DefaultHandler());

            // then retrieve the fully unmarshalled object
            try {
                JAXBElement<PurchaseOrderType> result = 
        (JAXBElement<PurchaseOrderType>)unmarshallerHandler.getResult();

                // process this new purchase order
                process(result.getValue());
            } catch( JAXBException je ) {
                // error was found during the unmarshalling.
                // you can either abort the processing by throwing a SAXException,
                // or you can continue processing by returning from this method.
                System.err.println("unable to process an order at line "+
                    locator.getLineNumber() );
                return;
            }

            unmarshallerHandler = null;
        }
    }
}

public void process( PurchaseOrderType order ) {
    System.out.println("this order will be shipped to "
        + order.getShipTo().getName() );
}

/**
 * Remembers the depth of the elements as we forward
 * SAX events to a JAXB unmarshaller.
 */
private int depth;

/**
 * Reference to the unmarshaller which is unmarshalling
 * an object.
 */
private UnmarshallerHandler unmarshallerHandler;


/**
 * Keeps a reference to the locator object so that we can later
 * pass it to a JAXB unmarshaller.
 */
private Locator locator;
public void setDocumentLocator(Locator locator) {
    super.setDocumentLocator(locator);
    this.locator = locator;
}


/**
 * Used to keep track of in-scope namespace bindings.
 * 
 * For JAXB unmarshaller to correctly unmarshal documents, it needs
 * to know all the effective namespace declarations.
 */
private NamespaceSupport namespaces = new NamespaceSupport();

public void startPrefixMapping(String prefix, String uri) throws SAXException {
    namespaces.pushContext();
    namespaces.declarePrefix(prefix,uri);

    super.startPrefixMapping(prefix, uri);
}

public void endPrefixMapping(String prefix) throws SAXException {
    namespaces.popContext();

    super.endPrefixMapping(prefix);
}

}

Primer.xsd

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:annotation>
    <xsd:documentation xml:lang="en">
      Purchase order schema for Example.com.
      Copyright 2000 Example.com. All rights reserved.
    </xsd:documentation>
  </xsd:annotation>


  <xsd:element name="purchaseOrders">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="purchaseOrder" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>


  <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>

  <xsd:element name="comment" type="xsd:string"/>

  <xsd:complexType name="PurchaseOrderType">
    <xsd:sequence>
      <xsd:element name="shipTo" type="USAddress"/>
      <xsd:element name="billTo" type="USAddress"/>
      <xsd:element ref="comment" minOccurs="0"/>
      <xsd:element name="items" type="Items"/>
    </xsd:sequence>
    <xsd:attribute name="orderDate" type="xsd:date"/>
  </xsd:complexType>

  <xsd:complexType name="USAddress">
    <xsd:sequence>
      <xsd:element name="name" type="xsd:string"/>
      <xsd:element name="street" type="xsd:string"/>
      <xsd:element name="city" type="xsd:string"/>
      <xsd:element name="state" type="xsd:string"/>
      <xsd:element name="zip" type="xsd:decimal"/>
    </xsd:sequence>
    <xsd:attribute name="country" type="xsd:NMTOKEN"
                   fixed="US"/>
  </xsd:complexType>

  <xsd:complexType name="Items">
    <xsd:sequence>
      <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="productName" type="xsd:string"/>
            <xsd:element name="quantity">
              <xsd:simpleType>
                <xsd:restriction base="xsd:positiveInteger">
                  <xsd:maxExclusive value="100"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="USPrice" type="xsd:decimal"/>
            <xsd:element ref="comment" minOccurs="0"/>
            <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
          </xsd:sequence>
          <xsd:attribute name="partNum" type="SKU" use="required"/>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <!-- Stock Keeping Unit, a code for identifying products -->
  <xsd:simpleType name="SKU">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="\d{3}-[A-Z]{2}"/>
    </xsd:restriction>
  </xsd:simpleType>

</xsd:schema>

test.xml< /em>

<purchaseOrders>
      <!-- 1st -->
      <purchaseOrder orderDate="1999-10-20">
        <shipTo country="US">
          <name>Alice Smith</name>
          <street>123 Maple Street</street>
          <city>Cambridge</city>
          <state>MA</state>
          <zip>12345</zip>
        </shipTo>
        <billTo country="US">
          <name>Robert Smith</name>
          <street>8 Oak Avenue</street>
          <city>Cambridge</city>
          <state>MA</state>
          <zip>12345</zip>
        </billTo>
        <items/>
      </purchaseOrder>
    </purchaseOrders>

I am using the partial-unmarshalling example of JAXB, but I am unable to unmarshal XML-Elements which are not on the root-level (cause they don't have an @XmlRootElement tag). In my example I tried to read the shipTo-Element instead of the purchaseOrder-Element.

Normally I would work with JAXBElement unmarshal(Source source,Class declaredType) but since the example is using an UnmarshallerHandler and a XMLFilterImpl I don't know where to tell Jaxb which Class it should use.

My error message is: Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"shipTo"). Expected elements are <{}comment>,<{}purchaseOrder>,<{}purchaseOrders>

I googled around a lot, but didn't find anything useful yet.

Here is the example code from the JaxB-Webpage:

Main.java

public class Main {
public static void main( String[] args ) throws Exception {

    // create JAXBContext for the primer.xsd
    JAXBContext context = JAXBContext.newInstance("primer");

    // create a new XML parser
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setNamespaceAware(true);
    XMLReader reader = factory.newSAXParser().getXMLReader();

    // prepare a Splitter
    Splitter splitter = new Splitter(context);

    // connect two components
    reader.setContentHandler(splitter);

    for( int i=0; i<args.length; i++ ) {
        // parse all the documents specified via the command line.
        // note that XMLReader expects an URL, not a file name.
        // so we need conversion.
        reader.parse(new File(args[i]).toURL().toExternalForm());
    }
}

}

Splitter.java

public class Splitter extends XMLFilterImpl {

public Splitter( JAXBContext context ) {
    this.context = context;
}

/**
 * We will create unmarshallers from this context.
 */
private final JAXBContext context;


public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
    throws SAXException {

    if( depth!= 0 ) {
        // we are in the middle of forwarding events.
        // continue to do so.
        depth++;
        super.startElement(namespaceURI, localName, qName, atts);
        return;
    }

    if( namespaceURI.equals("") && localName.equals("purchaseOrder") ) {
        // start a new unmarshaller
        Unmarshaller unmarshaller;
        try {
            unmarshaller = context.createUnmarshaller();
        } catch( JAXBException e ) {
            // there's no way to recover from this error.
            // we will abort the processing.
            throw new SAXException(e);
        }
        unmarshallerHandler = unmarshaller.getUnmarshallerHandler();

        // set it as the content handler so that it will receive
        // SAX events from now on.
        setContentHandler(unmarshallerHandler);

        // fire SAX events to emulate the start of a new document.
        unmarshallerHandler.startDocument();
        unmarshallerHandler.setDocumentLocator(locator);

        Enumeration e = namespaces.getPrefixes();
        while( e.hasMoreElements() ) {
            String prefix = (String)e.nextElement();
            String uri = namespaces.getURI(prefix);

            unmarshallerHandler.startPrefixMapping(prefix,uri);
        }
        String defaultURI = namespaces.getURI("");
        if( defaultURI!=null )
            unmarshallerHandler.startPrefixMapping("",defaultURI);

        super.startElement(namespaceURI, localName, qName, atts);

        // count the depth of elements and we will know when to stop.
        depth=1;
    }
}

public void endElement(String namespaceURI, String localName, String qName) throws SAXException {

    // forward this event
    super.endElement(namespaceURI, localName, qName);

    if( depth!=0 ) {
        depth--;
        if( depth==0 ) {
            // just finished sending one chunk.

            // emulate the end of a document.
            Enumeration e = namespaces.getPrefixes();
            while( e.hasMoreElements() ) {
                String prefix = (String)e.nextElement();
                unmarshallerHandler.endPrefixMapping(prefix);
            }
            String defaultURI = namespaces.getURI("");
            if( defaultURI!=null )
                unmarshallerHandler.endPrefixMapping("");
            unmarshallerHandler.endDocument();

            // stop forwarding events by setting a dummy handler.
            // XMLFilter doesn't accept null, so we have to give it something,
            // hence a DefaultHandler, which does nothing.
            setContentHandler(new DefaultHandler());

            // then retrieve the fully unmarshalled object
            try {
                JAXBElement<PurchaseOrderType> result = 
        (JAXBElement<PurchaseOrderType>)unmarshallerHandler.getResult();

                // process this new purchase order
                process(result.getValue());
            } catch( JAXBException je ) {
                // error was found during the unmarshalling.
                // you can either abort the processing by throwing a SAXException,
                // or you can continue processing by returning from this method.
                System.err.println("unable to process an order at line "+
                    locator.getLineNumber() );
                return;
            }

            unmarshallerHandler = null;
        }
    }
}

public void process( PurchaseOrderType order ) {
    System.out.println("this order will be shipped to "
        + order.getShipTo().getName() );
}

/**
 * Remembers the depth of the elements as we forward
 * SAX events to a JAXB unmarshaller.
 */
private int depth;

/**
 * Reference to the unmarshaller which is unmarshalling
 * an object.
 */
private UnmarshallerHandler unmarshallerHandler;


/**
 * Keeps a reference to the locator object so that we can later
 * pass it to a JAXB unmarshaller.
 */
private Locator locator;
public void setDocumentLocator(Locator locator) {
    super.setDocumentLocator(locator);
    this.locator = locator;
}


/**
 * Used to keep track of in-scope namespace bindings.
 * 
 * For JAXB unmarshaller to correctly unmarshal documents, it needs
 * to know all the effective namespace declarations.
 */
private NamespaceSupport namespaces = new NamespaceSupport();

public void startPrefixMapping(String prefix, String uri) throws SAXException {
    namespaces.pushContext();
    namespaces.declarePrefix(prefix,uri);

    super.startPrefixMapping(prefix, uri);
}

public void endPrefixMapping(String prefix) throws SAXException {
    namespaces.popContext();

    super.endPrefixMapping(prefix);
}

}

Primer.xsd

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:annotation>
    <xsd:documentation xml:lang="en">
      Purchase order schema for Example.com.
      Copyright 2000 Example.com. All rights reserved.
    </xsd:documentation>
  </xsd:annotation>


  <xsd:element name="purchaseOrders">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="purchaseOrder" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>


  <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>

  <xsd:element name="comment" type="xsd:string"/>

  <xsd:complexType name="PurchaseOrderType">
    <xsd:sequence>
      <xsd:element name="shipTo" type="USAddress"/>
      <xsd:element name="billTo" type="USAddress"/>
      <xsd:element ref="comment" minOccurs="0"/>
      <xsd:element name="items" type="Items"/>
    </xsd:sequence>
    <xsd:attribute name="orderDate" type="xsd:date"/>
  </xsd:complexType>

  <xsd:complexType name="USAddress">
    <xsd:sequence>
      <xsd:element name="name" type="xsd:string"/>
      <xsd:element name="street" type="xsd:string"/>
      <xsd:element name="city" type="xsd:string"/>
      <xsd:element name="state" type="xsd:string"/>
      <xsd:element name="zip" type="xsd:decimal"/>
    </xsd:sequence>
    <xsd:attribute name="country" type="xsd:NMTOKEN"
                   fixed="US"/>
  </xsd:complexType>

  <xsd:complexType name="Items">
    <xsd:sequence>
      <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="productName" type="xsd:string"/>
            <xsd:element name="quantity">
              <xsd:simpleType>
                <xsd:restriction base="xsd:positiveInteger">
                  <xsd:maxExclusive value="100"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="USPrice" type="xsd:decimal"/>
            <xsd:element ref="comment" minOccurs="0"/>
            <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
          </xsd:sequence>
          <xsd:attribute name="partNum" type="SKU" use="required"/>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <!-- Stock Keeping Unit, a code for identifying products -->
  <xsd:simpleType name="SKU">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="\d{3}-[A-Z]{2}"/>
    </xsd:restriction>
  </xsd:simpleType>

</xsd:schema>

test.xml

<purchaseOrders>
      <!-- 1st -->
      <purchaseOrder orderDate="1999-10-20">
        <shipTo country="US">
          <name>Alice Smith</name>
          <street>123 Maple Street</street>
          <city>Cambridge</city>
          <state>MA</state>
          <zip>12345</zip>
        </shipTo>
        <billTo country="US">
          <name>Robert Smith</name>
          <street>8 Oak Avenue</street>
          <city>Cambridge</city>
          <state>MA</state>
          <zip>12345</zip>
        </billTo>
        <items/>
      </purchaseOrder>
    </purchaseOrders>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

嗼ふ静 2024-11-24 00:19:05

我有这个确切的问题;尝试使用 jaxb 参考实现中的部分解组示例。

我确定的解决方案是将自定义 com.sun.xml.bind.api.ClassResolver 添加到上面的 startElement 方法中创建的解组器中。请参阅:

 try {
        unmarshaller = context.createUnmarshaller();
        unmarshaller.setProperty(ClassResolver.class.getName(), myClassResolver);
 } catch( JAXBException e ) {
...

这是一个模型解析器......

new ClassResolver()
    {
        @Override
        public Class<?> resolveElementName(String nsUri, String localName) throws Exception
        {
            if(MY_NAMESPACE.equals(nsUri) && MY_BAR.equals(localName))
                return BarType.class;
            else
                return null;
        }
    }

I had this precise issue; trying to use the partial-unmarshalling example from the jaxb reference implementation.

The solution I've settled upon is to add a custom com.sun.xml.bind.api.ClassResolver into the unmarshaller created in the startElement method, above. See:

 try {
        unmarshaller = context.createUnmarshaller();
        unmarshaller.setProperty(ClassResolver.class.getName(), myClassResolver);
 } catch( JAXBException e ) {
...

Here's a mockup resolver...

new ClassResolver()
    {
        @Override
        public Class<?> resolveElementName(String nsUri, String localName) throws Exception
        {
            if(MY_NAMESPACE.equals(nsUri) && MY_BAR.equals(localName))
                return BarType.class;
            else
                return null;
        }
    }
久随 2024-11-24 00:19:05

您的示例过于复杂(> 300 行)。请问,你能尝试使其适合 30 行代码吗?

实际上,JAXB 可以用 2 行代码解组流(假设您的类已正确注释):

private <T> T parse(URL url, Class<T> clazz) throws JAXBException {
  Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
  return clazz.cast(unmarshaller.unmarshal(url));
}

请参阅 此完整示例(带有测试)了解更多。

以及这篇文章了解有关该主题的更多信息。

Your sample is overcomplicated (> 300 lines). Please, can you try to make it fits on 30 lines of code?

In practice, JAXB can unmarshal a stream with 2 lines of code (assuming that your classes are correctly annotated):

private <T> T parse(URL url, Class<T> clazz) throws JAXBException {
  Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
  return clazz.cast(unmarshaller.unmarshal(url));
}

See this complete sample (with tests) for more.

And this article for even more on the subject.

向地狱狂奔 2024-11-24 00:19:05

您可以利用 SAXSource 来获取您正在寻找的行为:

InputSource inputSource = new InputSource(new File(args[i]).toURL().toExternalForm());
SAXSource saxSource = new SAXSource(reader, inputSource);
unmarshaller.unmarshal(saxSource, TargetClass.class);

完整示例:

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Main {
    public static void main( String[] args ) throws Exception {

        // create JAXBContext for the primer.xsd
        JAXBContext context = JAXBContext.newInstance("primer");

        // create a new XML parser
        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XMLReader reader = factory.newSAXParser().getXMLReader();

        // prepare a Splitter
        Splitter splitter = new Splitter(context);

        // connect two components
        reader.setContentHandler(splitter);

        Unmarshaller unmarshaller = context.createUnmarshaller();

        for( int i=0; i<args.length; i++ ) {
            // parse all the documents specified via the command line.
            // note that XMLReader expects an URL, not a file name.
            // so we need conversion.
            InputSource inputSource = new InputSource(new File(args[i]).toURL().toExternalForm());
            SAXSource saxSource = new SAXSource(reader, inputSource);
            unmarshaller.unmarshal(saxSource, TargetClass.class);
        }
    }

}

You could leverage a SAXSource to get the behaviour you are looking for:

InputSource inputSource = new InputSource(new File(args[i]).toURL().toExternalForm());
SAXSource saxSource = new SAXSource(reader, inputSource);
unmarshaller.unmarshal(saxSource, TargetClass.class);

Full Example:

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Main {
    public static void main( String[] args ) throws Exception {

        // create JAXBContext for the primer.xsd
        JAXBContext context = JAXBContext.newInstance("primer");

        // create a new XML parser
        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XMLReader reader = factory.newSAXParser().getXMLReader();

        // prepare a Splitter
        Splitter splitter = new Splitter(context);

        // connect two components
        reader.setContentHandler(splitter);

        Unmarshaller unmarshaller = context.createUnmarshaller();

        for( int i=0; i<args.length; i++ ) {
            // parse all the documents specified via the command line.
            // note that XMLReader expects an URL, not a file name.
            // so we need conversion.
            InputSource inputSource = new InputSource(new File(args[i]).toURL().toExternalForm());
            SAXSource saxSource = new SAXSource(reader, inputSource);
            unmarshaller.unmarshal(saxSource, TargetClass.class);
        }
    }

}
往昔成烟 2024-11-24 00:19:05

通常,当您尝试将子元素类作为参数传递给 jaxb 实例时,会引发此错误。尝试传递根类作为参数并检查它是否有效

Usually this error is thrown when you are trying to pass child element class as argument to jaxb instance. try passing root class as argument and check whether it will work or not

む无字情书 2024-11-24 00:19:05

这是我在这种情况下使用的功能。

/**
 * Loads an xml with a non <code>XmlRootElement</code> annotated element
 *
 * @param <T> Class to be unserialized
 * @param xmlStream {@link InputStream} The input stream of the xml file
 * @param modelClass <code>.class</code> of the model to read. This class may or not have the <code>XmlRootElement</code> annotation
 * @return {@link AppModel} Instance of the model
 * @throws JAXBException Error while reading the xml from the input stream
 */
public static <T> T readNonRootDataModelFromXml(InputStream xmlStream, Class<T> modelClass) throws JAXBException
{
    JAXBContext jaxbContext = JAXBContext.newInstance(modelClass);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
    JAXBElement<T> xmlRootElement = unmarshaller.unmarshal(new StreamSource(xmlStream), modelClass);
    return (T) xmlRootElement.getValue();
}

您可以将其放入静态 Utils 类中。

This is the function i use for such cases.

/**
 * Loads an xml with a non <code>XmlRootElement</code> annotated element
 *
 * @param <T> Class to be unserialized
 * @param xmlStream {@link InputStream} The input stream of the xml file
 * @param modelClass <code>.class</code> of the model to read. This class may or not have the <code>XmlRootElement</code> annotation
 * @return {@link AppModel} Instance of the model
 * @throws JAXBException Error while reading the xml from the input stream
 */
public static <T> T readNonRootDataModelFromXml(InputStream xmlStream, Class<T> modelClass) throws JAXBException
{
    JAXBContext jaxbContext = JAXBContext.newInstance(modelClass);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
    JAXBElement<T> xmlRootElement = unmarshaller.unmarshal(new StreamSource(xmlStream), modelClass);
    return (T) xmlRootElement.getValue();
}

You can put it in your static Utils class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文