【问题标题】:add xml:base to xml file in java在java中将xml:base添加到xml文件
【发布时间】:2009-04-03 19:18:22
【问题描述】:

我想在 java.xml 文件中添加一个 xml:base 声明。我目前在某个第三方代码生成的 OutputStream 中有 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">

我一定是脑子里放了屁什么的,因为我想不出一个务实的好方法。

有什么想法吗?

【问题讨论】:

    标签: java xml jena


    【解决方案1】:

    您可以通过获取适当的 RDFWriter 并将其 xmlbase 属性设置为您选择的 xmlbase 来更改 RDF/XML 序列化中使用的 xml:base。下面的代码从一个字符串中读取一个模型(这个问题的重要部分是关于如何编写模型,而不是它来自哪里),然后用 RDF/XML 将其写入两次,每次使用不同的xml:base

    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】:

      ByteArrayInputStream 无法适应大文件,而且我不喜欢使用临时文件的想法。我还认为将整个文件加载到 DOM 中只是为了添加 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】:

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

        注意:我让第三方应用程序将 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);
        

        我真的认为这会更容易。

        【讨论】:

        • 这比您发布的其他答案短,但比这更容易。读取模型后,只需设置写入器的xmlbase 属性并使用写入器编写模型。我已添加 an answer 显示此内容。
        猜你喜欢
        • 1970-01-01
        • 2013-03-16
        • 1970-01-01
        • 2013-03-10
        • 2011-03-03
        • 1970-01-01
        • 1970-01-01
        • 2011-12-17
        • 1970-01-01
        相关资源
        最近更新 更多