代码之家  ›  专栏  ›  技术社区  ›  Vinnie

在Java中添加XML:XML文件的基础

  •  0
  • Vinnie  · 技术社区  · 17 年前

    我想把一个XML:基本声明添加到Java中的XML文件中。我目前在一个由第三方代码生成的输出流中有XML输出。

    文件的开头如下:

    <rdf:RDF
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:owl="http://www.w3.org/2002/07/owl#"
        xmlns="http://www.mycompany.com/myNS#"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
        xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
    

    我希望它看起来像这样:

    <rdf:RDF
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:owl="http://www.w3.org/2002/07/owl#"
        xmlns="http://www.mycompany.com/myNS#"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
        xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
        xml:base="http://www.mycompany.com/myNS">
    

    我一定是在放个屁什么的,因为我想不出一个好方法来实事求是地做这件事。

    有什么想法吗?

    3 回复  |  直到 12 年前
        1
  •  1
  •   Joshua Taylor    12 年前

    你可以改变 xml:base 在RDF/XML序列化中使用,方法是获取适当的RDfWriter并设置其 xmlbase 您选择的属性 XMLBASE . 下面的代码从一个字符串中读取一个模型(这个问题的重要部分是如何编写模型,而不是从何处获取FRM),然后在RDF/XML中编写两次,每次使用不同的 XML:基础 .

    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import com.hp.hpl.jena.rdf.model.Model;
    import com.hp.hpl.jena.rdf.model.ModelFactory;
    import com.hp.hpl.jena.rdf.model.RDFWriter;
    
    public class ChangeBase {
        public static void main(String[] args) throws IOException {
            final String NS = "http://example.org/";
            final String text = "" +
                    "@prefix ex: <"+NS+">.\n" +
                    "ex:foo a ex:Foo .\n" +
                    "ex:foo ex:frob ex:bar.\n"; 
            final Model model = ModelFactory.createDefaultModel();
            try ( final InputStream in = new ByteArrayInputStream( text.getBytes() )) {
                model.read( in, null, "TTL" );
            }
            // get a writer for RDF/XML-ABBREV, set its xmlbase to the NS, and write the model
            RDFWriter writer = model.getWriter( "RDF/XML-ABBREV" );
            writer.setProperty( "xmlbase", NS );
            writer.write( model, System.out, null );
    
            // change the base to example.com (.com, not .org) and write again
            writer.setProperty( "xmlbase", "http://example.com" );
            writer.write( model, System.out, null );
        }
    }
    

    输出是(注意,在第一种情况下,基是 htttp://example.org/ 在第二种情况下, http://example.com (区别是.org与.com):

    <rdf:RDF
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:ex="http://example.org/"
      xml:base="http://example.org/">
      <ex:Foo rdf:about="foo">
        <ex:frob rdf:resource="bar"/>
      </ex:Foo>
    </rdf:RDF>
    
    <rdf:RDF
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:ex="http://example.org/"
      xml:base="http://example.com">
      <ex:Foo rdf:about="http://example.org/foo">
        <ex:frob rdf:resource="http://example.org/bar"/>
      </ex:Foo>
    </rdf:RDF>
    
        2
  •  -1
  •   Vinnie    17 年前

    bytearrayinputstream不能扩展为大型文件,我不喜欢使用临时文件的想法。我还认为仅仅为了添加 xml:base 标签。

    这里有一个使用管道和简单的手工解析代码添加标签的替代解决方案。

    PipedInputStream pipedInput = new PipedInputStream();
    PipedOutputStream pipedOutput = new PipedOutputStream(pipedInput);
    new Thread(new ModelExportThread(model, pipedOutput)).start();
    int bufferSize = 1024;
    byte[] bytes = new byte[bufferSize];            
    StringBuffer stringBuffer = new StringBuffer();
    int bytesRead = pipedInput.read(bytes, 0, bufferSize);
    boolean done = false;
    String startRDF = "<rdf:RDF";
    while (bytesRead > 0) {
        if (!done) {
            stringBuffer.append(new String(bytes, 0, bytesRead));
            int startIndex = stringBuffer.indexOf(startRDF);
            if ((startIndex >= 0)) {
                stringBuffer.insert(startIndex + startRDF.length(), " xml:base=\"" + namespace + "\"");
                outputStream.write(stringBuffer.toString().getBytes());
                stringBuffer.setLength(0);
                done = true;
            }
        } else {
            outputStream.write(bytes, 0, bytesRead);
        }
        bytesRead = pipedInput.read(bytes, 0, bufferSize);
    }
    outputStream.flush();
    

    这是要写入输出管道的线程代码。

    public class ModelExportThread implements Runnable {
    
        private final OntModel model;
        private final OutputStream outputStream;
    
        public ModelExportThread(OntModel model, OutputStream outputStream) {
            this.model = model;
            this.outputStream = outputStream;
        }
    
        public void run() {
            try {
                model.write(outputStream, "RDF/XML-ABBREV");
                outputStream.flush();
                outputStream.close();
            } catch (IOException ex) {
                Logger.getLogger(OntologyModel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
    }
    
        3
  •  -1
  •   Vinnie    17 年前

    经过一些挖掘,这就是我所做的。

    注意:我让第三方应用程序将XML写入StringWriter,而不是名为“Writer”的输出流。outputstream'是结果XML将写入的流的名称。

    ByteArrayInputStream inputStream = new ByteArrayInputStream(writer.toString().getBytes());
    Document myXML = 
         DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
    myXML.getDocumentElement().setAttribute("xml:base", namespace);
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    StreamResult result = new StreamResult(outputStream);
    DOMSource source = new DOMSource(myXML);
    transformer.transform(source, result);
    

    我真的认为这会更容易些。