如何循环使用lambda的XMLStreamReader
问题描述:
这对于学习的目的而言,是一个比真正需要更多的问题。 我正在使用下面的代码来检查一个xml文件是否有效。我不担心这里的模式验证。 我知道的XMLStreamReader是一个接口,但我试图找到一些FPGA实现,让我做一些接近:如何循环使用lambda的XMLStreamReader
Stream<String> s = reader.getText();
s.forEach(System.out::println);
//我的完整代码,而无需拉姆达
public interface CheckXml {
default boolean readFile(String f) throws IOException {
Boolean result = false;
FileInputStream inputStream = null;
try {
XMLInputFactory factory = XMLInputFactory.newInstance();
inputStream = new FileInputStream(f);
XMLStreamReader reader = factory.createXMLStreamReader(inputStream);
while (reader.hasNext()) {
reader.next();
}
} catch (IOException e) {
e.printStackTrace();
throw e;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
inputStream.close();
}
}
return result;
}
//编辑
import com.iread.CheckXml;
public class CheckXmlFiles implements CheckXml {
}
//...
@Test
public void testXmlValidation() throws IOException {
CheckXml c = new CheckXmlFiles();
assertTrue("For simplicity it is expected 'true'", c.readFile("C:\\_pocs\\temp\\demo.xml"));
}
答
您可以将XmlStreamReader
转换为流,然后使用它。它需要您创建一个迭代器,例如调用hasNext
和next
方法。
执行过程中有一些令人头痛的事情:XmlStreamReader抛出检查异常,这将迫使您创建一些额外的异常处理代码,从而使代码膨胀。
另请注意,底层到XmlStreamReader
的流必须在迭代器内部关闭。如果您在外面关闭它,您将面临一些流封闭异常。在这种情况下,您不能使用try with resources
。
我试图创建一个简单的流和一个简单的测试来计算XML文件中可用的元素数量。
下面是一些玩具的代码演示如何最终能做到这一点:
public class XMLStreamReaderStream {
public static Stream<Integer> fromFile(File f) throws IOException, XMLStreamException {
XMLInputFactory factory = XMLInputFactory.newInstance();
Reader inputStream;
inputStream = new InputStreamReader(new FileInputStream(f), "UTF-8");
XMLStreamReader reader = factory.createXMLStreamReader(inputStream);
Iterator<Integer> iterator = new Iterator<>() {
public Integer next() {
try {
return reader.next();
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
public boolean hasNext() {
try {
boolean hasNext = reader.hasNext();
if (!hasNext) {
reader.close(); // close the stream here
}
return hasNext;
} catch (XMLStreamException e) {
return false;
}
}
public void forEachRemaining(Consumer<? super Integer> action) {
while (hasNext()) {
action.accept(next());
}
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
}
public static void main(String[] args) throws IOException, XMLStreamException {
File sampleXml = new File("stackoverflow1.xml");
LinkedHashMap<Integer, Long> xmlStats = fromFile(sampleXml).collect(Collectors.groupingBy(Function.identity(),
LinkedHashMap::new, Collectors.counting()));
Map<String, Long> readableMap = xmlStats.entrySet().stream().collect(Collectors.toMap(e -> {
Optional<Field> opt = Stream.of(XMLStreamConstants.class.getDeclaredFields()).filter(f -> {
try {
return e.getKey().equals(f.get(null));
} catch (IllegalAccessException e1) {
return false;
}
}).findFirst();
return opt.map(s -> s.toString().replaceAll(".+\\.", "")).orElseGet(() -> Integer.toString(e.getKey()));
}, Map.Entry::getValue));
System.out.println(readableMap);
}
}
此代码将计算类型的XML文件中找到的标签并打印到控制台:
{START_ELEMENT=22, END_DOCUMENT=1, END_ELEMENT=22, CHARACTERS=27}
您的“没有lambda的完整代码”对我来说看起来并不完整。它应该至少包含获得你想要在'Stream'中输入的字符串的代码。 –
Eran
创建一个'Iterator',其中'Something'是''while'期间想要出的东西 - 例如'XMLElement'或'Person'。将'Iterator'包裹在'Spliterator'中。从Spliterator创建一个Stream。 –
@坦率地说,我不知道这个问题有什么关系,但是在这里;我加入了我的问题 – DemeCarv