我有可以将文件保存为各种格式(所有格式均为xml)的应用程序。因此,我应该确定保存哪种格式的文件来解决问题。所以,我看到了两种解决方案

  • 不同的格式具有不同的架构,因此我可以由它们确定。
    我以从here
  • 获得的方式设置模式
    marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "bla-bla.xsd");
    所以我想我可以使用unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION)获得它

    但它抛出



    getSchema()返回null
    那么,如何获取架构位置?
  • 使用setAdapter(Class<A> type, A adapter)方法
  • 为不同的bean指定不同的适配器

    哪种方法更可取?如果是第一个,那么如何获取架构位置标签?

    upd 代码示例
    假设我们有 bean
    @XmlRootElement
    public class Foo{
        String bar;
        public String getBar() {return bar; }
        public void setBar(String bar) {this.bar = bar;}
    }
    

    以及生成模式,保存Foo实例并随后加载的代码。
    public class Test {
        final static String schemaLoc = "fooschema.xsd";
    
    
        public static void write(File file, Foo foo, Schema schema) throws Throwable {
            XMLEventWriter xsw = null;
            try{
                JAXBContext context = JAXBContext.newInstance(Foo.class);
                XMLOutputFactory xof = XMLOutputFactory.newInstance();
                OutputStream out = new FileOutputStream(file);
                xsw = xof.createXMLEventWriter(out);
                Marshaller m = context.createMarshaller();
                m.setSchema(schema);    //schema setted
                System.out.println(">>>marchal : " + m.getSchema());    //check it
                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                m.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, schemaLoc);
                m.marshal(foo, xsw);
            } finally{
                 xsw.close();
            }
        }
    
        public static Foo load(File file) throws Throwable {
            JAXBContext context = JAXBContext.newInstance(Foo.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
    
    
            System.out.println("unmarshaller schema:" + unmarshaller.getSchema());  //I need get it here
        //  System.out.println("schema_prop:" + unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION));
    
            InputStreamReader in = new InputStreamReader(new FileInputStream(file));
            XMLEventReader xer = XMLInputFactory.newInstance()
                    .createXMLEventReader(in);
            return Foo.class.cast(unmarshaller.unmarshal(xer));
        }
    
        private static File createSchema(String schemaLocation) throws Throwable{
            final File target = new File(schemaLocation);
            if(!target.exists()){
                JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class);
                SchemaOutputResolver sor = new SchemaOutputResolver() {
                    public Result createOutput(String namespaceURI, String suggestedFileName)
                    throws IOException {
                        StreamResult result = new StreamResult(target);
                        result.setSystemId(target.toURI().toURL().toString());
                        return result;
                    }
                };
                jaxbContext.generateSchema(sor);
            }
            return target;
        }
    
        public static void main(String[] args) throws Throwable {
            createSchema(schemaLoc);
            File file = new File("temp.xml");
            Foo foo = new Foo();
            foo.setBar("test bar");
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema schema = factory.newSchema(createSchema(schemaLoc));
            write(file, foo, schema);
            System.out.println("result " + load(file).getBar());
        }
    
    }
    

    生成的模式


          <xs:element name="foo" type="foo"/>
    
          <xs:complexType name="foo">
            <xs:sequence>
              <xs:element name="bar" type="xs:string" minOccurs="0"/>
            </xs:sequence>
          </xs:complexType>
        </xs:schema>
    

    我们的临时文件
    <?xml version="1.0"?>
    <foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="fooschema.xsd">
    <bar>test bar</bar></foo>
    

    如我们所见,有



    如何使用JAXB获得此文本?

    最佳答案

    我将利用StAX解析器来获取此信息(请参见下面的示例)。在输入上创建一个XMLStreamReader。使用nextTag()方法将XMLStreamReader推进到根元素。然后,获取根元素的noNamespaceSchemaLocation属性。然后将XMLStreamReader传递给Unmarshaller上的unmarshal(XMLStreamReader)方法。

    import java.io.FileInputStream;
    import javax.xml.XMLConstants;
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Unmarshaller;
    import javax.xml.stream.XMLInputFactory;
    import javax.xml.stream.XMLStreamReader;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext context = JAXBContext.newInstance(Categories.class);
    
            XMLInputFactory xif = XMLInputFactory.newInstance();
            FileInputStream fis = new FileInputStream("input.xml");
            XMLStreamReader xsr = xif.createXMLStreamReader(fis);
            xsr.nextTag();
            String noNamespaceSchemaLocation = xsr.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "noNamespaceSchemaLocation");
            System.out.println(noNamespaceSchemaLocation);
    
            Unmarshaller um = context.createUnmarshaller();
            Categories response = (Categories) um.unmarshal(xsr);
        }
    }
    

    关于java - JAXB中的解码器和架构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4478666/

    10-16 17:07