@Before可能会有一些重复的问题建议,我不认为可能是这种情况,请先阅读本章,我会尽量简短。标题给出了基本思路。
这是一个XML示例(案例1):
<root>
<Item>
<ItemID>4504216603</ItemID>
<ListingDetails>
<StartTime>10:00:10.000Z</StartTime>
<EndTime>10:00:30.000Z</EndTime>
<ViewItemURL>http://url</ViewItemURL>
....
</item>
这是一个XML示例(案例2):
<Item>
<ItemID>4504216604</ItemID>
<ListingDetails>
<StartTime>10:30:10.000Z</StartTime>
<!-- Start difference from case 1 -->
<averages>
<AverageTime>value1</AverageTime>
<category type="TX">9823</category>
<category type="TY">9112</category>
<AveragePrice>value2</AveragePrice>
</averages>
<!-- End difference from case 1 -->
<EndTime>11:00:10.000Z</EndTime>
<ViewItemURL>http://url</ViewItemURL>
....
</item>
</root>
我从Google借用了这种XML,无论如何,我的对象并不总是相同的,有时还有像case2这样的额外元素。现在,我想从两种情况下生成这样的CSV:
ItemID,StartTime,EndTime,ViewItemURL,AverageTime,AveragePrice
4504216603,10:00:10.000Z,10:00:30.000Z,http://url
4504216604,10:30:10.000Z,11:00:10.000Z,http://url,value1,value2
这第一行是标头,它也应包含在csv中。我今天有一些有用的指向stax的链接,我真的不知道什么是正确/最佳方法,我已经为此苦苦挣扎了3天,还真不愿意放弃。
告诉我您的想法如何解决
我忘了提及这是非常大的xml文件,最大容量为1gb
赏金更新:
我正在寻找更通用的方法,这意味着它应该适用于任何深度的任意数量的节点,有时像在示例xml中一样,可能发生一个item
对象的节点数量多于下一个/上一个对象的情况,因此也应如此(因此所有列和值在CSV中都匹配)。
同样可能发生的是,节点具有相同的名称/本地名称,但值和属性不同,如果是这种情况,则新列应以适当的值显示在CSV中。(我在<averages>
标记中添加了这种情况的示例category
)
提供的代码应被视为是草图,而不是权威的文章。我不是SAX方面的专家,可以改进实现以获得更好的性能,更简单的代码等。这表示SAX应该能够处理流较大的XML文件。
我将使用SAX解析器通过2次传递来解决此问题。(顺便说一句,我还将使用CSV生成库来创建输出,因为这将处理CSV涉及的所有巧妙的字符转义,但我并未在草图中实现)。
第一遍: 建立标题列数
第二次通过: 输出CSV
我认为XML文件格式正确。我假设我们没有预定义顺序的方案/ DTD。
在第一遍中,我假设将为包含文本内容的每个XML元素或任何属性添加CSV列(我假设属性将包含某些内容!)。
确定目标列数的第二遍将执行实际的CSV输出。
根据您的示例XML,我的代码草图将产生:
ItemID,StartTime,EndTime,ViewItemURL,AverageTime,category,category,type,type,AveragePrice
4504216603,10:00:10.000Z,10:00:30.000Z,http://url,,,,,,
4504216604,10:30:10.000Z,11:00:10.000Z,http://url,value1,9823,9112,TX,TY,value2
请注意,我使用了Google集合LinkedHashMultimap,因为这在将多个值与单个键关联时非常有用。希望这个对你有帮助!
import com.google.common.collect.LinkedHashMultimap;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
public class App {
public static void main(String[] args) throws SAXException, FileNotFoundException, IOException {
// First pass - to determine headers
XMLReader xr = XMLReaderFactory.createXMLReader();
HeaderHandler handler = new HeaderHandler();
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
FileReader r = new FileReader("test1.xml");
xr.parse(new InputSource(r));
LinkedHashMap<String, Integer> headers = handler.getHeaders();
int totalnumberofcolumns = 0;
for (int headercount : headers.values()) {
totalnumberofcolumns += headercount;
}
String[] columnheaders = new String[totalnumberofcolumns];
int i = 0;
for (Entry<String, Integer> entry : headers.entrySet()) {
for (int j = 0; j < entry.getValue(); j++) {
columnheaders[i] = entry.getKey();
i++;
}
}
StringBuilder sb = new StringBuilder();
for (String h : columnheaders) {
sb.append(h);
sb.append(',');
}
System.out.println(sb.substring(0, sb.length() - 1));
// Second pass - collect and output data
xr = XMLReaderFactory.createXMLReader();
DataHandler datahandler = new DataHandler();
datahandler.setHeaderArray(columnheaders);
xr.setContentHandler(datahandler);
xr.setErrorHandler(datahandler);
r = new FileReader("test1.xml");
xr.parse(new InputSource(r));
}
public static class HeaderHandler extends DefaultHandler {
private String content;
private String currentElement;
private boolean insideElement = false;
private Attributes attribs;
private LinkedHashMap<String, Integer> itemHeader;
private LinkedHashMap<String, Integer> accumulativeHeader = new LinkedHashMap<String, Integer>();
public HeaderHandler() {
super();
}
private LinkedHashMap<String, Integer> getHeaders() {
return accumulativeHeader;
}
private void addItemHeader(String headerName) {
if (itemHeader.containsKey(headerName)) {
itemHeader.put(headerName, itemHeader.get(headerName) + 1);
} else {
itemHeader.put(headerName, 1);
}
}
@Override
public void startElement(String uri, String name,
String qName, Attributes atts) {
if ("item".equalsIgnoreCase(qName)) {
itemHeader = new LinkedHashMap<String, Integer>();
}
currentElement = qName;
content = null;
insideElement = true;
attribs = atts;
}
@Override
public void endElement(String uri, String name, String qName) {
if (!"item".equalsIgnoreCase(qName) && !"root".equalsIgnoreCase(qName)) {
if (content != null && qName.equals(currentElement) && content.trim().length() > 0) {
addItemHeader(qName);
}
if (attribs != null) {
int attsLength = attribs.getLength();
if (attsLength > 0) {
for (int i = 0; i < attsLength; i++) {
String attName = attribs.getLocalName(i);
addItemHeader(attName);
}
}
}
}
if ("item".equalsIgnoreCase(qName)) {
for (Entry<String, Integer> entry : itemHeader.entrySet()) {
String headerName = entry.getKey();
Integer count = entry.getValue();
//System.out.println(entry.getKey() + ":" + entry.getValue());
if (accumulativeHeader.containsKey(headerName)) {
if (count > accumulativeHeader.get(headerName)) {
accumulativeHeader.put(headerName, count);
}
} else {
accumulativeHeader.put(headerName, count);
}
}
}
insideElement = false;
currentElement = null;
attribs = null;
}
@Override
public void characters(char ch[], int start, int length) {
if (insideElement) {
content = new String(ch, start, length);
}
}
}
public static class DataHandler extends DefaultHandler {
private String content;
private String currentElement;
private boolean insideElement = false;
private Attributes attribs;
private LinkedHashMultimap dataMap;
private String[] headerArray;
public DataHandler() {
super();
}
@Override
public void startElement(String uri, String name,
String qName, Attributes atts) {
if ("item".equalsIgnoreCase(qName)) {
dataMap = LinkedHashMultimap.create();
}
currentElement = qName;
content = null;
insideElement = true;
attribs = atts;
}
@Override
public void endElement(String uri, String name, String qName) {
if (!"item".equalsIgnoreCase(qName) && !"root".equalsIgnoreCase(qName)) {
if (content != null && qName.equals(currentElement) && content.trim().length() > 0) {
dataMap.put(qName, content);
}
if (attribs != null) {
int attsLength = attribs.getLength();
if (attsLength > 0) {
for (int i = 0; i < attsLength; i++) {
String attName = attribs.getLocalName(i);
dataMap.put(attName, attribs.getValue(i));
}
}
}
}
if ("item".equalsIgnoreCase(qName)) {
String data[] = new String[headerArray.length];
int i = 0;
for (String h : headerArray) {
if (dataMap.containsKey(h)) {
Object[] values = dataMap.get(h).toArray();
data[i] = (String) values[0];
if (values.length > 1) {
dataMap.removeAll(h);
for (int j = 1; j < values.length; j++) {
dataMap.put(h, values[j]);
}
} else {
dataMap.removeAll(h);
}
} else {
data[i] = "";
}
i++;
}
StringBuilder sb = new StringBuilder();
for (String d : data) {
sb.append(d);
sb.append(',');
}
System.out.println(sb.substring(0, sb.length() - 1));
}
insideElement = false;
currentElement = null;
attribs = null;
}
@Override
public void characters(char ch[], int start, int length) {
if (insideElement) {
content = new String(ch, start, length);
}
}
public void setHeaderArray(String[] headerArray) {
this.headerArray = headerArray;
}
}
}
问题内容: 我需要帮助来理解使用java将XML文件转换为CSV文件所涉及的步骤。这是XML文件的示例 这是生成的CSV文件。 我当时正在考虑使用DOM解析器读取xml文件。我遇到的问题是,我需要按名称指定要编码的特定元素,但我希望它能够解析它而不这样做。 Java中是否有任何工具或库可以帮助我实现这一目标。 如果我下面有这种格式的XML文件,并且想在与MSgId相同的行中添加InitgPty的值
问题内容: 我是json的新手。我有一个程序可以从json对象生成xml。 输出为: 我最大的问题是如何编写自己的属性而不是json_type =“ number”,以及如何编写自己的子元素,例如。 问题答案: 使用中的(优秀)JSON-Java库,然后 可以使用第二个参数来提供XML根节点的名称。 该库还能够使用以下命令将XML转换为JSON POM
我想将 xml 文件转换为路径。 例如,我有一个xml文件,其中包含: 我想要的结果是这样的: Person.name = 测试, person . address . address 1 = Test。 有什么解决办法能让我这么做吗?
给我最好的方式来写代码。 如何在C#中将XML文件转换为CSV文件,只显示以下标记: 输出CSV文件格式应如下所示:
问题内容: 我使用APKTool对Android应用程序进行了反向工程,并获得了.Smali文件作为源代码输出。我将带有应用程序的.Smali文件转换为.Java文件。我能够成功编辑.Java文件,但现在我想将它们转换回.Smali,以便可以使用新的.Smali文件重新编译应用程序。当我只留下.Java文件时,它不会重新编译并给出一些错误。我在互联网上找不到有关将.Java编译为.Smali的任何
我有一堆XML文档(源),需要将它们转换为具有不同结构(目标)的POJO。我的第一个明显的想法是使用JAXB和XSLT的组合。然而,在一些问题上,我不确定这是否合适。 我无法访问源的XSD。 我不需要目标作为XML结构,而只需要作为POJOs。 然后我想创建一个映射表,比如。 然而,这将导致大量“映射”代码,特别是在涉及复杂数据类型的情况下。 你对我如何实施这一点有什么建议吗?