2009-04-03 7 views
0

Я хочу добавить объявление xml: base в XML-файл в java. В настоящее время у меня есть выход xml в OutputStream, который был сгенерирован некоторым сторонним кодом.Добавить xml: base в xml файл в java

Файл начинается так:

<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"> 

Я должен быть с пердеть мозга или что-то, потому что я не могу думать хорошего способа сделать это прагматично.

Любые идеи?

ответ

-1

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); 
     } 
    } 

} 
-1

После некоторого рытья это то, что я сделал.

ПРИМЕЧАНИЕ. У стороннего приложения было написано 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); 

Я действительно думал, что это будет проще.

+0

Это меньше, чем другой ответ, который вы опубликовали, но это еще проще, чем это. После того, как вы прочитали модель, вы просто установите свойство 'xmlbase' писателя и используете автора для написания модели. Я добавлен [ответ] (http://stackoverflow.com/a/18987916/1281433), показывающий это. –

1

Вы можете изменить xml:base используемые в RDF/XML сериализации пути получения соответствующего RDFWriter и установив его свойство xmlbase на выбранный xmlbase. Следующий код читает модель из строки (важная часть этого вопроса заключается в том, как писать модель, а не в том месте, где она есть), а затем записывает ее в 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>