我需要在Java中对具有相同属性的XML元素进行分组。
以下是我更新的输入:
<root>
<Slots date="2015-11-17">
<TimePeriod value="8-17">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298451</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
<Slots date="2015-11-17">
<TimePeriod value="8-17">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298452</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
<Slots date="2015-11-18">
<TimePeriod value="2-8">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298451</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
<Slots date="2015-11-18">
<TimePeriod value="2-8">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298452</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
我需要输出如下:
<root>
<Slots date="2015-11-17">
<TimePeriod value="8-17">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298451</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298452</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
<Slots date="2015-11-18">
<TimePeriod value="2-8">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298451</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298452</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
</root>
我尝试了类似下面的内容:
HashSet<String> set = new HashSet<String>();
if( node!= null && node.getLength() > 0) {
for(int i=0;i<node.getLength();i=i+1)
{
Node slots = node.item(i);
set.add(slots.getAttributes().getNamedItem("date").getNodeValue());
}
}
System.out.println("slots dates are --- **** "+ set);
ArrayList<Node> deleteList = new ArrayList<Node>();
for(String date : set)
{ System.out.println("slots dates is --- **** "+ "2015-11-18");
Node remainingNode = null;
for(int i=0;i<node.getLength();i=i+1)
{
Node slotnode = node.item(i);
if( slotnode.getAttributes() != null && slotnode.getAttributes().getNamedItem("date")!= null && "2015-11-18".equals(slotnode.getAttributes().getNamedItem("date").getNodeValue()))
{System.out.println("inside time 18");
if(remainingNode == null)
remainingNode = slotnode;
else {
NodeList nodeps = slotnode.getChildNodes();
for(int j=0;j<nodeps.getLength();j=i+1) {
remainingNode.appendChild(nodeps.item(j));
}
deleteList.add(slotnode);
}
}
}
NodeList nodesItems = doc1.getElementsByTagName("root");
nodesItems.item(0).appendChild(remainingNode);
我尝试使用Dom解析器,但我无法做到。我是XML的新手,到处搜索但没找到任何东西,任何人都可以帮助我。 注意:我不能将JAXB用于此解决方案。
是的,我按日期分组插槽,然后另外按TimePeriod值。 我正在使用的工具
不支持XSLT答案 0 :(得分:0)
首先,您的XML文件格式不正确。这是格式良好的版本:
<root>
<Slots date="2015-11-17">
<TimePeriod value="8-17">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298451</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
<Slots date="2015-11-17">
<TimePeriod value="8-17">
<ContractorAvailable ContractorID="H4CONT07">
<GroupId>298452</GroupId>
<OfferToken>10315009</OfferToken>
<Capacity>99</Capacity>
</ContractorAvailable>
</TimePeriod>
</Slots>
</root>
这是一个示例,说明如何访问XML文件中的数据:
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;
public class XMLParser {
public static void main(String argv[]) {
try {
File fXmlFile = new File("C:/test.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
System.out.println("Root element in this XML file is :" + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("ContractorAvailable");
System.out.println("----------------------------");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println("Contractor ID : " + eElement.getAttribute("ContractorID"));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果将如下:
当您可以访问数据时,可以创建一个新的XML文件。
答案 1 :(得分:0)
正如我在评论中所说,我认为这对于XSLT 2.0(例如可用于Java,例如分别使用http://mvnrepository.com/artifact/net.sf.saxon/Saxon-HE中的Saxon 9.6 HE http://sourceforge.net/projects/saxon/files/Saxon-HE/9.6/SaxonHE9-6-0-7J.zip/download)和以下XSLT代码来说是一项轻松的工作:< / p>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:for-each-group select="Slots" group-by="@date">
<Slots date="{current-grouping-key()}">
<xsl:for-each-group select="current-group()/TimePeriod" group-by="@value">
<TimePeriod value="{current-grouping-key()}">
<xsl:copy-of select="current-group()/ContractorAvailable"/>
</TimePeriod>
</xsl:for-each-group>
</Slots>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:transform>
如果你想用Java进行分组,Java 8支持这个,但是DOM并不是真正合适的数据结构,所以你需要首先构建一个List<Element>
,然后再构建一个新的import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.SAXException;
public class DOMGroupBy1 {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document inputDoc = db.parse("input.xml");
Document outputDoc = db.newDocument();
outputDoc.appendChild(outputDoc.createElement("root"));
NodeList domSlots = inputDoc.getElementsByTagName("Slots");
List<Element> slots = new ArrayList<>();
for (int i = 0; i < domSlots.getLength(); i++) {
slots.add((Element) domSlots.item(i));
}
List<Element> groups
= slots
.stream()
.collect(Collectors.groupingBy(slot -> slot.getAttribute("date")))
.entrySet()
.stream()
.map(entry -> {
Element newSlot = outputDoc.createElement("Slots");
newSlot.setAttribute("date", entry.getKey());
entry
.getValue()
.stream()
.collect(Collectors.groupingBy(slot -> ((Element) slot.getElementsByTagName("TimePeriod").item(0)).getAttribute("value")))
.entrySet()
.forEach(time -> {
Element timeEl = outputDoc.createElement("TimePeriod");
timeEl.setAttribute("value", time.getKey());
newSlot.appendChild(timeEl);
time.getValue().forEach(el -> {
NodeList cas = el.getElementsByTagName("ContractorAvailable");
for (int j = 0; j < cas.getLength(); j++) {
timeEl.appendChild(outputDoc.importNode(cas.item(j), true));
}
});
});
return newSlot;
})
.collect(Collectors.toList());
LSSerializer serializer = ((DOMImplementationLS) db.getDOMImplementation()).createLSSerializer();
serializer.getDomConfig().setParameter("format-pretty-print", true);
groups.forEach(slot -> outputDoc.getDocumentElement().appendChild(slot));
System.out.println(serializer.writeToString(outputDoc)); // could of course write a file here instead with e.g. serializer.writeToURI(outputDoc, new File("result.xml").toURI().toString());
}
}
DOM:
string
答案 2 :(得分:0)
感谢您的所有答案,但我能够使用以下代码进行分组。希望它可能有助于其他人寻找相同的东西。
package beans;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.TreeSet;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class Grouping {
/**
* Gets the first child element of a node.
* @param node the node to get the child from
* @return the first element child of the given Node
*
*/
public static Element getFirstChildElement(Node node)
{
node = node.getFirstChild();
while (node != null && node.getNodeType() != Node.ELEMENT_NODE)
{
node = node.getNextSibling();
}
return (Element)node;
}
/**
* Groups the Given Nodes based on the tag value. Tag should be present in as attribute in the root tag.
* @ NodeList List of Nodes for which grouping needs to be done
* @String Group Tag name based on its values, the nodes will be grouped
* @return boolean true/false.
*
*/
public static boolean groupNodes(NodeList slotNodes, String strGroupTag)
{
// Start checking the unique Values for grouping
TreeSet<String> slotdates = new TreeSet<String>();
if( slotNodes!= null && slotNodes.getLength() > 0) {
for(int i=0;i<slotNodes.getLength();i++)
{
Node slots = slotNodes.item(i);
if(slots != null && slots.getAttributes() != null)
{
String strDate = slots.getAttributes().getNamedItem(strGroupTag).getNodeValue();
slotdates.add(strDate);
}
}
}
// Ends : checking the unique Values for grouping
// Starts Grouping based on dates
ArrayList<Node> deleteSlotList = new ArrayList<Node>();
for(String slotdate : slotdates)
{
Node remainingSlotNode = null;
for(int i=0;i<slotNodes.getLength();i++)
{
Node slotnode = slotNodes.item(i);
if( slotnode.getAttributes() != null && slotnode.getAttributes().getNamedItem(strGroupTag)!= null)
{
String strDateValue = slotnode.getAttributes().getNamedItem(strGroupTag).getNodeValue();
if(strDateValue != null && strDateValue.equalsIgnoreCase(slotdate))
{
if(remainingSlotNode == null)
{
remainingSlotNode = slotnode;
}
else {
Node NodeTime = getFirstChildElement(slotnode);
if(NodeTime != null)
{
remainingSlotNode.appendChild(NodeTime);
}
deleteSlotList.add(slotnode);
}
}
}
}
slotNodes.item(0).getParentNode().appendChild(remainingSlotNode);
}
for(Node deletedNode: deleteSlotList)
{
deletedNode.getParentNode().removeChild(deletedNode);
}
// Ends Grouping based on dates
return true;
}
public static DOMSource groupingUtil(String xml) throws TransformerException, SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new StringReader(xml)));
NodeList slotNodes = doc.getElementsByTagName("Slots");
if(groupNodes(slotNodes, "date"))
{
slotNodes = doc.getElementsByTagName("Slots");
for(int i=0;i<slotNodes.getLength();i++)
{
Node slot = slotNodes.item(i);
NodeList timeNodes = slot.getChildNodes();
groupNodes(timeNodes, "value");
}
}
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
return source;
}
}