我如何使用 Apache Daffodil 的 DataProcessor.unparse() 方法来重构原始的已解析消息?
How can I use Apache Daffodil's DataProcessor.unparse() method to reconstitute the original parsed message?
我是 Apache Daffodil 的初学者。
我使用 Daffodil Java API 将输入文本消息成功解析为 XML 字符串,即
Compiler dfdlCompiler = Daffodil.compiler();
dfdlCompiler.setValidateDFDLSchemas(true);
File schemaFile = this.getFileFromResources("EDIFACT-SupplyChain-D03B/EDIFACT-SupplyChain-Messages-D.03B.xsd");
ProcessorFactory processorFactory = dfdlCompiler.compileFile(schemaFile);
DataProcessor dataProcessor = processorFactory.onPath("/");
java.io.File file = getFileFromResources("TestData/ORDERS_D.03B_Interchange.txt");
java.io.FileInputStream fis = new java.io.FileInputStream(file);
InputSourceDataInputStream dis = new InputSourceDataInputStream(fis);
JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();
ParseResult parseResult = dataProcessor.parse(dis, outputter);
Document doc = outputter.getResult().getDocument();
XMLOutputter xo = new XMLOutputter(org.jdom2.output.Format.getPrettyFormat());
String xmlString = xo.outputString(doc);
System.out.println("parsed text... resulting xmlString=" + xmlString);
但是,现在,我不清楚如何使用 unparse() 方法来重构原始文本消息(似乎缺乏使用 Daffodil 的 Java API 来解析为重构原始消息)。
试试这个:
SAXBuilder builder = new SAXBuilder();
Document d2 = builder.build(new StringReader(xmlString));
JDOMInfosetInputter inputter = new JDOMInfosetInputter(d2);
WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
UnparseResult result = dataProcessor.unparse(inputter, output);
如何提取原始消息?或者,这种做法不正确吗?
Apache Daffodil 版本:2.3
Java版本:jdk8+
正在使用这个略微精简的 Java 应用程序进行测试...
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import org.jdom2.Document;
import org.jdom2.output.XMLOutputter;
import org.apache.daffodil.japi.Compiler;
import org.apache.daffodil.japi.Daffodil;
import org.apache.daffodil.japi.DataProcessor;
import org.apache.daffodil.japi.ParseResult;
import org.apache.daffodil.japi.ProcessorFactory;
import org.apache.daffodil.japi.UnparseResult;
import org.apache.daffodil.japi.infoset.JDOMInfosetInputter;
import org.apache.daffodil.japi.infoset.JDOMInfosetOutputter;
import org.apache.daffodil.japi.io.InputSourceDataInputStream;
import org.jdom2.input.SAXBuilder;
public class Blah2 {
public static void main(String[] args) throws IOException, Exception {
Blah2 b = new Blah2();
b.process();
}
private void process() throws IOException, Exception {
Compiler dfdlCompiler = Daffodil.compiler();
dfdlCompiler.setValidateDFDLSchemas(true);
File schemaFile = this.getFileFromResources("EDIFACT-SupplyChain-D03B/EDIFACT-SupplyChain-Messages-D.03B.xsd");
ProcessorFactory processorFactory = dfdlCompiler.compileFile(schemaFile);
DataProcessor dataProcessor = processorFactory.onPath("/");
java.io.File file = getFileFromResources("TestData/ORDERS_D.03B_Interchange.txt");
java.io.FileInputStream fis = new java.io.FileInputStream(file);
InputSourceDataInputStream dis = new InputSourceDataInputStream(fis);
JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();
ParseResult parseResult = dataProcessor.parse(dis, outputter);
Document doc = outputter.getResult().getDocument();
XMLOutputter xo = new XMLOutputter(org.jdom2.output.Format.getPrettyFormat());
String xmlString = xo.outputString(doc);
System.out.println("parsed text... resulting xmlString=" + xmlString);
SAXBuilder builder = new SAXBuilder();
Document d2 = builder.build(new StringReader(xmlString));
JDOMInfosetInputter inputter = new JDOMInfosetInputter(d2);
WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
UnparseResult result = dataProcessor.unparse(inputter, output);
System.out.println("unparsed xml document.. result.toString()=" + String.valueOf(result));
//how can I obtain the original input text???
}
private File getFileFromResources(String fileName) throws IOException {
URL resource = this.getClass().getClassLoader().getResource(fileName);
return new File(resource.getFile());
}
}
解析操作的输出如下。
(我仍然不明白如何完成相反的操作 - 即 "unparse")
parsed text... resulting xmlString=<?xml version="1.0" encoding="UTF-8"?>
<D03B:Interchange xmlns:D03B="http://www.ibm.com/dfdl/edi/un/edifact/SupplyChain/D03B">
<UNB>
<S001>
<E0001>UNOA</E0001>
<E0002>4</E0002>
</S001>
<S002>
<E0004>APPLICATION</E0004>
<E0007>1</E0007>
</S002>
<S003>
<E0010>COMPANY</E0010>
<E0007>1</E0007>
</S003>
<S004>
<E0017>20051107</E0017>
<E0019>1159</E0019>
</S004>
<E0020>6002</E0020>
</UNB>
<D03B:Message>
<UNH>
<E0062>SSDD1</E0062>
<S009>
<E0065>ORDERS</E0065>
<E0052>D</E0052>
<E0054>03B</E0054>
<E0051>UN</E0051>
<E0057>EAN008</E0057>
</S009>
</UNH>
<D03B:BadMessage>
<Segment>
<Name>BGM</Name>
<Data>2B3232302B424B4F4439392B39</Data>
</Segment>
<Segment>
<Name>DTM</Name>
<Data>2B3133373A32303035313130373A313032</Data>
</Segment>
<Segment>
<Name>NAD</Name>
<Data>2B42592B353431323334353030303137363A3A39</Data>
</Segment>
<Segment>
<Name>NAD</Name>
<Data>2B53552B343031323334353030303039343A3A39</Data>
</Segment>
<Segment>
<Name>CTA</Name>
<Data>2B4141</Data>
</Segment>
<Segment>
<Name>COM</Name>
<Data>2B7331313A41412A7332313A41412A7333313A4141</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B312B312B303736343536393130343A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3235</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B4C6F7264206F66207468652052696E6773</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B322B312B303736343536393039303A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3235</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B54686520486F62626974</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B332B312B313836313030343635363A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3136</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B5468652053696C6D6172696C6C696F6E</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B342B312B303539363030363735363A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3130</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B546865204368696C6472656E206F6620487572696E</Data>
</Segment>
<Segment>
<Name>UNS</Name>
<Data>2B53</Data>
</Segment>
<Segment>
<Name>CNT</Name>
<Data>2B323A34</Data>
</Segment>
</D03B:BadMessage>
<UNT>
<E0074>22</E0074>
<E0062>SSDD1</E0062>
</UNT>
</D03B:Message>
<UNZ>
<E0036>1</E0036>
<E0020>6002</E0020>
</UNZ>
</D03B:Interchange>
unparsed xml document.. result.toString()=org.apache.daffodil.japi.UnparseResult@2e734540
UnparseResult
实际不包含未解析的结果(是的,也许我们可以更好地命名它;)。 UnparseResult
实际上只包含解析是否成功(通过 isError
方法)以及失败时的任何诊断。未解析的数据将写入您作为参数传递给 unparse()
的 WritableByteChannel
。
问题是,在您的情况下,您可以通过以下方式定义该频道:
WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
所以您定义的通道写入底层 ByteArrayOutputStream
,但您无权访问这些字节,因为它没有分配给变量。所以你真正想要做的是将一个 ByteArrayOutputStream
分配给一个变量并将其传递给你的新通道,然后在解析之后访问字节数组——就像这样:
ByteArrayOutputStream boas = new ByteArrayOutputStream();
WritableByteChannel output = Channels.newChannel(new DataOutputStream(boas));
UnparseResult result = dataProcessor.unparse(inputter, output);
System.out.println(boas.toString());
此外,Daffodil Java API 用法的一些好资源是我们的 Java API 测试:
其中包含使用 ByteArrayOutputStream 和 WritableByteChannel 来解析字节并转换为字符串的示例。
我是 Apache Daffodil 的初学者。
我使用 Daffodil Java API 将输入文本消息成功解析为 XML 字符串,即
Compiler dfdlCompiler = Daffodil.compiler();
dfdlCompiler.setValidateDFDLSchemas(true);
File schemaFile = this.getFileFromResources("EDIFACT-SupplyChain-D03B/EDIFACT-SupplyChain-Messages-D.03B.xsd");
ProcessorFactory processorFactory = dfdlCompiler.compileFile(schemaFile);
DataProcessor dataProcessor = processorFactory.onPath("/");
java.io.File file = getFileFromResources("TestData/ORDERS_D.03B_Interchange.txt");
java.io.FileInputStream fis = new java.io.FileInputStream(file);
InputSourceDataInputStream dis = new InputSourceDataInputStream(fis);
JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();
ParseResult parseResult = dataProcessor.parse(dis, outputter);
Document doc = outputter.getResult().getDocument();
XMLOutputter xo = new XMLOutputter(org.jdom2.output.Format.getPrettyFormat());
String xmlString = xo.outputString(doc);
System.out.println("parsed text... resulting xmlString=" + xmlString);
但是,现在,我不清楚如何使用 unparse() 方法来重构原始文本消息(似乎缺乏使用 Daffodil 的 Java API 来解析为重构原始消息)。
试试这个:
SAXBuilder builder = new SAXBuilder();
Document d2 = builder.build(new StringReader(xmlString));
JDOMInfosetInputter inputter = new JDOMInfosetInputter(d2);
WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
UnparseResult result = dataProcessor.unparse(inputter, output);
如何提取原始消息?或者,这种做法不正确吗?
Apache Daffodil 版本:2.3
Java版本:jdk8+
正在使用这个略微精简的 Java 应用程序进行测试...
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import org.jdom2.Document;
import org.jdom2.output.XMLOutputter;
import org.apache.daffodil.japi.Compiler;
import org.apache.daffodil.japi.Daffodil;
import org.apache.daffodil.japi.DataProcessor;
import org.apache.daffodil.japi.ParseResult;
import org.apache.daffodil.japi.ProcessorFactory;
import org.apache.daffodil.japi.UnparseResult;
import org.apache.daffodil.japi.infoset.JDOMInfosetInputter;
import org.apache.daffodil.japi.infoset.JDOMInfosetOutputter;
import org.apache.daffodil.japi.io.InputSourceDataInputStream;
import org.jdom2.input.SAXBuilder;
public class Blah2 {
public static void main(String[] args) throws IOException, Exception {
Blah2 b = new Blah2();
b.process();
}
private void process() throws IOException, Exception {
Compiler dfdlCompiler = Daffodil.compiler();
dfdlCompiler.setValidateDFDLSchemas(true);
File schemaFile = this.getFileFromResources("EDIFACT-SupplyChain-D03B/EDIFACT-SupplyChain-Messages-D.03B.xsd");
ProcessorFactory processorFactory = dfdlCompiler.compileFile(schemaFile);
DataProcessor dataProcessor = processorFactory.onPath("/");
java.io.File file = getFileFromResources("TestData/ORDERS_D.03B_Interchange.txt");
java.io.FileInputStream fis = new java.io.FileInputStream(file);
InputSourceDataInputStream dis = new InputSourceDataInputStream(fis);
JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();
ParseResult parseResult = dataProcessor.parse(dis, outputter);
Document doc = outputter.getResult().getDocument();
XMLOutputter xo = new XMLOutputter(org.jdom2.output.Format.getPrettyFormat());
String xmlString = xo.outputString(doc);
System.out.println("parsed text... resulting xmlString=" + xmlString);
SAXBuilder builder = new SAXBuilder();
Document d2 = builder.build(new StringReader(xmlString));
JDOMInfosetInputter inputter = new JDOMInfosetInputter(d2);
WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
UnparseResult result = dataProcessor.unparse(inputter, output);
System.out.println("unparsed xml document.. result.toString()=" + String.valueOf(result));
//how can I obtain the original input text???
}
private File getFileFromResources(String fileName) throws IOException {
URL resource = this.getClass().getClassLoader().getResource(fileName);
return new File(resource.getFile());
}
}
解析操作的输出如下。
(我仍然不明白如何完成相反的操作 - 即 "unparse")
parsed text... resulting xmlString=<?xml version="1.0" encoding="UTF-8"?>
<D03B:Interchange xmlns:D03B="http://www.ibm.com/dfdl/edi/un/edifact/SupplyChain/D03B">
<UNB>
<S001>
<E0001>UNOA</E0001>
<E0002>4</E0002>
</S001>
<S002>
<E0004>APPLICATION</E0004>
<E0007>1</E0007>
</S002>
<S003>
<E0010>COMPANY</E0010>
<E0007>1</E0007>
</S003>
<S004>
<E0017>20051107</E0017>
<E0019>1159</E0019>
</S004>
<E0020>6002</E0020>
</UNB>
<D03B:Message>
<UNH>
<E0062>SSDD1</E0062>
<S009>
<E0065>ORDERS</E0065>
<E0052>D</E0052>
<E0054>03B</E0054>
<E0051>UN</E0051>
<E0057>EAN008</E0057>
</S009>
</UNH>
<D03B:BadMessage>
<Segment>
<Name>BGM</Name>
<Data>2B3232302B424B4F4439392B39</Data>
</Segment>
<Segment>
<Name>DTM</Name>
<Data>2B3133373A32303035313130373A313032</Data>
</Segment>
<Segment>
<Name>NAD</Name>
<Data>2B42592B353431323334353030303137363A3A39</Data>
</Segment>
<Segment>
<Name>NAD</Name>
<Data>2B53552B343031323334353030303039343A3A39</Data>
</Segment>
<Segment>
<Name>CTA</Name>
<Data>2B4141</Data>
</Segment>
<Segment>
<Name>COM</Name>
<Data>2B7331313A41412A7332313A41412A7333313A4141</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B312B312B303736343536393130343A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3235</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B4C6F7264206F66207468652052696E6773</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B322B312B303736343536393039303A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3235</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B54686520486F62626974</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B332B312B313836313030343635363A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3136</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B5468652053696C6D6172696C6C696F6E</Data>
</Segment>
<Segment>
<Name>LIN</Name>
<Data>2B342B312B303539363030363735363A4942</Data>
</Segment>
<Segment>
<Name>QTY</Name>
<Data>2B313A3130</Data>
</Segment>
<Segment>
<Name>FTX</Name>
<Data>2B41464D2B312B2B546865204368696C6472656E206F6620487572696E</Data>
</Segment>
<Segment>
<Name>UNS</Name>
<Data>2B53</Data>
</Segment>
<Segment>
<Name>CNT</Name>
<Data>2B323A34</Data>
</Segment>
</D03B:BadMessage>
<UNT>
<E0074>22</E0074>
<E0062>SSDD1</E0062>
</UNT>
</D03B:Message>
<UNZ>
<E0036>1</E0036>
<E0020>6002</E0020>
</UNZ>
</D03B:Interchange>
unparsed xml document.. result.toString()=org.apache.daffodil.japi.UnparseResult@2e734540
UnparseResult
实际不包含未解析的结果(是的,也许我们可以更好地命名它;)。 UnparseResult
实际上只包含解析是否成功(通过 isError
方法)以及失败时的任何诊断。未解析的数据将写入您作为参数传递给 unparse()
的 WritableByteChannel
。
问题是,在您的情况下,您可以通过以下方式定义该频道:
WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
所以您定义的通道写入底层 ByteArrayOutputStream
,但您无权访问这些字节,因为它没有分配给变量。所以你真正想要做的是将一个 ByteArrayOutputStream
分配给一个变量并将其传递给你的新通道,然后在解析之后访问字节数组——就像这样:
ByteArrayOutputStream boas = new ByteArrayOutputStream();
WritableByteChannel output = Channels.newChannel(new DataOutputStream(boas));
UnparseResult result = dataProcessor.unparse(inputter, output);
System.out.println(boas.toString());
此外,Daffodil Java API 用法的一些好资源是我们的 Java API 测试:
其中包含使用 ByteArrayOutputStream 和 WritableByteChannel 来解析字节并转换为字符串的示例。