输入(fullInput
)
假设我将以下内容作为 InputStream
(或从该流读取的内存中的 String
):
<?xml version="1.0" ?>
<root>
<element attr="val1"><x /><y /></element>
<element attr="val2"><y /></element>
<element attr="val3"><x /><x /></element>
<element attr="val4"><z /><y /></element>
</root>
我想如何使用该解决方案 (bridgeXml
)
IProprietaryUnmarshaller UNMARSHALLER = ...;
List<Element> parseFullXml(String fullInput) throws UnmarshallException {
List<String> inputs = bridgeXml(fullInput);
List<Element> outputs = new ArrayList();
for(String input : inputs) {
Element e = UNMARSHALLER.unmarshall(input);
outputs.add(e);
}
return outputs;
}
我在找什么
我正在寻找 bridgeXml
的实现/想法,其中输入 String
/*Stream
被分成更小的 block 本身就是格式良好的 XML 文档(没有 XML 声明)的字符串。
我想避免的琐碎实现
下面的实现容易出错,不灵活,不应该使用,我正在寻找一个使用某种库或 XML 解析器的合适的实现!
List<String> bridgeXml(String input) {
// strip anything up to the opening root element, and LTrim the remainder
input = input.replaceAll("(?s)^.*<root.*?>\\s*", "");
// strip anything after the closing root element, and RTrim the remainder
input = input.replaceAll("(?s)\\s*</root.*$", "");
// split at </element> closing tags, not removing them (?<= does the magic)
return Arrays.asList(input.split("(?<=</element>)"));
}
限制
- XML 输入无法更改,并且是完全有效的 XML。
- 必须使用专有的解码器,不能修改。
- 我正在寻找一种解决方案,其中文件不是 XML 解码、XML 编码、专有解码。
- (不要挑剔 XML/Java 代码风格、格式、可见性修饰符等!
这些是便于交流的简化代码。)
解决方案(编辑)
我最终写下了这篇文章...我最终对 XML 进行了双重解析(请参阅 getOuterXml
),因为现在就认为它很慢还为时过早。在此之后我有一个巨大的数据库查询,速度要慢得多。
protected <T> List<T> read(InputStream inputStream, String tagName) throws XMLStreamException,
TransformerException, DecodingException
{
List<T> result = new ArrayList<T>();
XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
XMLStreamReader xmlReader = xmlFactory.createXMLStreamReader(inputStream, "ISO-8859-1");
while (xmlReader.hasNext()) {
xmlReader.next();
if (xmlReader.isStartElement() && tagName.equals(xmlReader.getLocalName())) {
String output = getOuterXml(xmlReader);
@SuppressWarnings("unchecked")
T object = (T) UNMARSHALLER.unmarshall(output);
result.add(object);
}
}
return result;
}
protected String getOuterXml(XMLStreamReader xmlr) throws TransformerException
{
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter stringWriter = new StringWriter();
transformer.transform(new StAXSource(xmlr), new StreamResult(stringWriter));
return stringWriter.toString();
}
protected <T> List<T> getObjects(String urlString, String tagName)
{
LOG.info("Downloading [{}] updates from [{}].", tagName, urlString);
HttpURLConnection conn = null;
InputStream inputStream = null;
try {
URL url = new URL(urlString);
conn = (HttpURLConnection) url.openConnection();
conn.connect();
inputStream = conn.getInputStream();
return read(inputStream, tagName);
} catch (Exception ex) {
String exceptionMessage = "Updating [" + tagName + "] from [" + urlString + "] failed.";
LOG.error(exceptionMessage, ex);
throw new MyFancyWrapperException(exceptionMessage, ex);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ex) {
LOG.warn("Cannot close HTTP's input stream", ex);
}
}
if (conn != null) {
conn.disconnect();
}
}
}
最佳答案
所以这是一个用于示例 xml 的小型 stax 解析器:
String xml = "<root><element>test</element></root>";
XMLInputFactory xmlif = XMLInputFactory.newInstance();
XMLStreamReader xmlr = xmlif.createXMLStreamReader(new StringReader(xml));
while (xmlr.hasNext()) {
xmlr.next();
if (xmlr.isStartElement() || xmlr.isEndElement()) {
System.out.println(xmlr.getLocalName() + " " + xmlr.getEventType());
}
}
在这里你会找到一个解释,你可以如何将 stax 与 jaxb 结合起来。
http://blog.bdoughan.com/2012/08/handle-middle-of-xml-document-with-jaxb.html
关于java - 如何部分解析 XML(仅 1 层深),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21767834/