我想在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">
我必须有一个大脑放屁或其他东西,因为我无法想出一个实用的好方法。
有什么想法吗?
答案 0 :(得分:1)
您可以通过获取相应的RDFWriter并将其xml:base
属性设置为您选择的xmlbase
来更改RDF / XML序列化中使用的xmlbase
。下面的代码从字符串中读取模型(这个问题的重要部分是关于如何编写模型,而不是它来自frm的位置),然后将其写入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>
答案 1 :(得分:-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);
我真的认为这会更容易。
答案 2 :(得分:-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);
}
}
}