【发布时间】:2014-09-09 13:45:17
【问题描述】:
我需要获取我认为“非常规”的 XML 文件,并将其转换为我认为的“常规”文件。下面的 XML 示例已经“清除”了专有名称/值。
“非常规”的 XML 文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<dataView name="document/aDocument" xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataItems>
<dataItem name="item1" location="item1" dataItemType="Long">
<value xsi:type="xs:string">1</value>
</dataItem>
<dataItem name="item2" location="item.seconditem(some item).ref" dataItemType="String">
<value xsi:type="xs:string">ABC2DEF3</value>
</dataItem>
</dataItems>
<dataRepeaters>
<dataRepeater name="SomeLevel1" runtimeInfomration="SomeLevel11984371030">
<dataGroups>
<dataGroup name="SomeLevel2" location="SomeLevel:(a level).thelevel" keyValue="SomeLevel119843710300" runtimeInformation="19843710300">
<dataItems>
<dataItem name="someItem1" location="someLevel.aLevel(another item)" dataItemType="String">
<value xsi:type="xs:string">12345</value>
</dataItem>
<dataItem name="someItem2" location="someLevel.aLevel(another item2)" dataItemType="Integer"/>
<dataItem name="someItem3" location="someLevel.aLevel(another item3)" dataItemType="ObjectReference">
<value xsi:type="xs:string">11:20012:3536</value>
</dataItem>
<dataItem name="someItem4" location="someLevel.aLevel(another item4)" dataItemType="String"/>
<dataItem name="someItem5" location="someLevel.aLevel(another item5)" dataItemType="String">
<value xsi:type="xs:string">someItem5 Data</value>
</dataItem>
<dataItem name="someItem6" location="someLevel.aLevel(another item6)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">123456:USD</value>
</dataItem>
</dataItems>
</dataGroup>
<dataGroup name="SomeLevel3" keyValue="SomeLevel31984371030" runtimeInformation="1984371030">
<dataRepeaters>
<dataRepeater name="SomeLevel4" runtimeInfomration="SomeLevel4">
<dataGroups>
<dataGroup name="SomeLevel5" location="anotherLevel.level5(SomeLevel5):someLevel5" keyValue="SomeLevel51984371030-11521863690" runtimeInformation="1984371030-11521863690">
<dataItems>
<dataItem name="someItem6" location="someLevel.aLevel(another item6)" dataItemType="BigDecimal">
<value xsi:type="xs:string">303.149</value>
</dataItem>
<dataItem name="someItem7" location="someLevel.aLevel(another item7)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">117:USD</value>
</dataItem>
<dataItem name="someItem8" location="someLevel.aLevel(another item8)" dataItemType="String">
<value xsi:type="xs:string">117.000000:USD</value>
</dataItem>
<dataItem name="someItem9" location="someLevel.aLevel(another item9)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">117:USD</value>
</dataItem>
</dataItems>
<dataRepeaters>
<dataRepeater name="SomeLevel6" runtimeInfomration="someLevel6">
<dataGroups/>
</dataRepeater>
</dataRepeaters>
</dataGroup>
<dataGroup name="SomeLevel7" location="anotherLevel.level5(SomeLevel7):someLevel7" keyValue="SomeLevel71984371030-11521863690" runtimeInformation="1984371030-11521863690">
<dataItems>
<dataItem name="someItem10" location="someLevel.aLevel(another item10)" dataItemType="BigDecimal">
<value xsi:type="xs:string">292.741</value>
</dataItem>
<dataItem name="someItem11" location="someLevel.aLevel(another item11)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">165:USD</value>
</dataItem>
<dataItem name="someItem12" location="someLevel.aLevel(another item12)" dataItemType="String">
<value xsi:type="xs:string">165.000000:USD</value>
</dataItem>
<dataItem name="someItem13" location="someLevel.aLevel(another item13)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">165:USD</value>
</dataItem>
</dataItems>
<dataRepeaters/>
</dataGroup>
<dataGroup name="SomeLevel8" location="anotherLevel.level5(SomeLevel8):someLevel8" keyValue="SomeLevel81984371030-11521863690" runtimeInformation="1984371030-11521863690">
<dataItems>
<dataItem name="someItem14" location="someLevel.aLevel(another item14)" dataItemType="BigDecimal">
<value xsi:type="xs:string">369.075</value>
</dataItem>
<dataItem name="someItem15" location="someLevel.aLevel(another item15)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">598:USD</value>
</dataItem>
<dataItem name="someItem16" location="someLevel.aLevel(another item16)" dataItemType="String">
<value xsi:type="xs:string">598.000000:USD</value>
</dataItem>
</dataItems>
<dataRepeaters>
<dataRepeater name="SomeLevel9" runtimeInfomration="someLevel9">
<dataGroups>
<dataGroup name="SomeLevel10" location="ownedAuto.AgreementActual(Liability).ConstantRole(Policy Form):policyForm" keyValue="aomeLevel101984371030-11521863690-115218636900" runtimeInformation="1984371030-11521863690-115218636900">
<dataItems>
<dataItem name="someItem17" location="someLevel.aLevel(another item17)" dataItemType="String">
<value xsi:type="xs:string">Some Data | ABC 123</value>
</dataItem>
<dataItem name="someItem18" location="someLevel.aLevel(another item18)" dataItemType="Integer">
<value xsi:type="xs:string">2</value>
</dataItem>
</dataItems>
</dataGroup>
</dataGroups>
</dataRepeater>
<dataRepeater name="SomeLevel10" runtimeInfomration="someLevel11">
<dataGroups/>
</dataRepeater>
</dataRepeaters>
</dataGroup>
</dataGroups>
</dataRepeater>
</dataRepeaters>
</dataGroup>
</dataGroups>
</dataRepeater>
</dataRepeaters>
</dataView>
我正在尝试将其转换为以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<dataView name="document/aDocument" xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item1>1</item1>
<item2>ABC2DEF3</item2>
<SomeLevel1>
<SomeLevel2>
<someItem1>12345f</someItem1>
<someItem2></someItem2>
<someItem3>11:20012:3536</someItem3>
<someItem4>12345f</someItem4>
<someItem5>someItem5 Data</someItem5>
<someItem6>123456:USD</someItem6>
</SomeLevel2>
<SomeLevel3>
<SomeLevel4>
<SomeLevel5>
<someItem7>303.149</someItem7>
<someItem8>117:USD</someItem8>
<someItem9>117.000000:USD</someItem9>
<someItem10>117:USD</someItem10>
<SomeLevel6></SomeLevel6>
</SomeLevel5>
<SomeLevel7>
<someItem11>292.741</someItem11>
<someItem12>165:USD</someItem12>
<someItem13>165.000000:USD</someItem13>
<someItem14>165:USD</someItem14>
</SomeLevel7>
<SomeLevel8>
<someItem15>369.075</someItem15>
<someItem16>598:USD</someItem16>
<someItem17>598.000000:USD</someItem17>
<SomeLevel9>
<SomeLevel10>
<someItem18>Some Data | ABC 123</someItem18>
<someItem19>2</someItem19>
</SomeLevel10>
</SomeLevel9>
<SomeLevel11></SomeLevel11>
</SomeLevel8>
</SomeLevel4>
</SomeLevel3>
</SomeLevel1>
</dataView>
所以基本上我试图采用“名称”属性并将其作为 XML 节点/标签和 <value> 节点/标签之间的值,并将其用作 XML 节点/标签的“值”。
我尝试了几种不同的解析/编写“例程”,以下两个是最接近我的两个。所以我忽略了其他的,因为它们只是“噪音”。
这是我迄今为止尝试过的:
private Document xmlDocument;
public void convertXML() {
xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader("DSExample.xml")));
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Node dsNode = xmlDocument.getDocumentElement();
xmlDocument = docBuilder.newDocument();
// Attempt 1:
doSomethingDS(dsNode); // This will convert the XML but with NO nesting - creates example output 1
// Attempt 2:
traverseDS(dsNode); // This will create an XML with ONLY the root dataItems - Don't know why - creates example output 2
}
public void doSomethingDS(Node node) {
System.out.println(node.getNodeName());
Element xmlElement = null;
// This will be the "root" element/node "dataView":
if(node.getNodeName() != null && node.getNodeName().equalsIgnoreCase("dataView")) {
// Debugging: Print the node
printNode(node);
String nodeName = node.getNodeName().trim();
rootElement = xmlDocument.createElement(nodeName);
mPreviousElement = rootElement;
addAllAttributesToRootElement((Element) node, rootElement);
xmlDocument.appendChild(rootElement);
}
else {
// Debugging: Print the node
printNode(node);
// If has "name" property - create element/node
if(node.getAttributes() != null && node.getAttributes().getNamedItem("name") != null) {
xmlElement = createElement(xmlDocument, node);
if(xmlElement !=null && xmlDocument.getFirstChild() != null) {
xmlDocument.getFirstChild().appendChild(xmlElement);
}
}
}
NodeList nodeList = node.getChildNodes();
for(int i = 0; i < nodeList.getLength(); i++) {
Node currentNode = nodeList.item(i);
if(currentNode.getNodeType() == Node.ELEMENT_NODE) {
// recursively call this method for all the children which are of type Element
doSomethingDS(currentNode);
}
}
} // End of doSomethingDS()
public void traverseDS(Node parentNode) {
// This will create an XML with ONLY the root dataItems - Don't know why.
Element xmlElement = null;
//****************************************************************
// This will be the "root" element/node "dataView":
if(parentNode.getNodeName() != null && parentNode.getNodeName().equalsIgnoreCase("dataView")) {
// Debugging: Print the node
printNode(parentNode);
String nodeName = parentNode.getNodeName().trim();
rootElement = xmlDocument.createElement(nodeName);
mPreviousElement = rootElement;
if(!isRootNodeSet) {
mRootNode = parentNode;
isRootNodeSet = true;
}
addAllAttributesToRootElement((Element) parentNode, rootElement);
xmlDocument.appendChild(rootElement);
// traverse children
Node theNode = parentNode.getFirstChild();
if(theNode != null) {
theNode = theNode.getNextSibling();
}
else if (isRootNodeSet) {
theNode = mRootNode.getNextSibling();
}
traverseDS(theNode);
}
else {
// traverse all nodes that belong to the parent
for(Node theNode = parentNode.getFirstChild(); theNode != null; theNode = theNode.getNextSibling()) {
// Debugging: Print the node
printNode(theNode);
// If has "name" property - create element/node
if(theNode.getAttributes() != null && theNode.getAttributes().getNamedItem("name") != null) {
// Create new Element/Node
xmlElement = createElement(xmlDocument, theNode);
if(xmlElement !=null && xmlDocument.getFirstChild() != null) {
xmlDocument.getFirstChild().appendChild(xmlElement);
}
else {
System.out.println(" not a node we wanted?");
}
}
// traverse children
traverseDS(theNode);
}
}
} // End of traverseDS()
private Element createElement(Document aDoc, Node aNode) {
Element xmlElement = null;
String elementName = "";
NamedNodeMap dataNodeMap = aNode.getAttributes();
if(dataNodeMap != null && dataNodeMap.getNamedItem("name") != null) {
elementName = dataNodeMap.getNamedItem("name").getTextContent();
xmlElement = aDoc.createElement(elementName);
// if node = "dataItem" - walk node to get <value> node
// Note: some "dataItem" nodes also have a <previousValue> node - what to do with these????
if(aNode.getNodeName() != null && aNode.getNodeName().equalsIgnoreCase("dataItem")) {
// Walk Node to get <value> node
NodeList childNodes = aNode.getChildNodes();
int childNodesLength = childNodes.getLength();
for(int x = 0; x < childNodesLength; x++) {
Node childNode = childNodes.item(x);
if(childNode.getNodeName() != null && childNode.getNodeName().equalsIgnoreCase("value")) {
xmlElement.setTextContent(childNode.getTextContent());
break;
}
}
}
}
return xmlElement;
} // End of createElement()
示例输出 1(由 doSomethingDS() 创建):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="document/aDocument">
<item1>1</item1>
<item2>ABC2DEF3</item2>
<SomeLevel1/>
<SomeLevel2/>
<someItem1>12345</someItem1>
<someItem2/>
<someItem3>11:20012:3536</someItem3>
<someItem4/>
<someItem5>someItem5 Data</someItem5>
<someItem6>123456:USD</someItem6>
<SomeLevel3/>
<SomeLevel4/>
<SomeLevel5/>
<someItem6>303.149</someItem6>
<someItem7>117:USD</someItem7>
<someItem8>117.000000:USD</someItem8>
<someItem9>117:USD</someItem9>
<SomeLevel6/>
<SomeLevel7/>
<someItem10>292.741</someItem10>
<someItem11>165:USD</someItem11>
<someItem12>165.000000:USD</someItem12>
<someItem13>165:USD</someItem13>
<SomeLevel8/>
<someItem14>369.075</someItem14>
<someItem15>598:USD</someItem15>
<someItem16>598.000000:USD</someItem16>
<SomeLevel9/>
<SomeLevel10/>
<someItem17>Some Data | ABC 123</someItem17>
<someItem18>2</someItem18>
<SomeLevel11/>
</dataView>
示例输出 2(由 traverseDS() 创建):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="document/aDocument">
<item1>1</item1>
<item2>ABC2DEF3</item2>
</dataView>
现在是这个问题.... 我得到的是动态的,我可以一次得到一辆 Mac 卡车,下一次得到一辆丰田,或者两者兼而有之。我得到的 XML 的大小可能很小也可能很大。所以很难只使用 XPath 或直接使用特定元素,因为我不知道我会得到什么。这就是为什么我基本上一次遍历 DOM 一个节点以提取出可用的内容。
所以我的问题是: 我在解析/写入 XML 文件时做错了什么,没有让它看起来像我试图让它看起来的样子?
【问题讨论】:
-
您是否考虑过一些 XSLT 转换来完成这项工作?
-
似乎你总是在
doSomethingDS()中附加到dataView元素,因为你总是在调用xmlDocument.getFirstChild().appendChild(xmlElement)。我猜您需要跟踪您正在遍历的元素并将新元素附加到该元素。
标签: java xml xml-parsing