如何按属性

时间:2015-11-19 13:49:24

标签: java xml domparser

我需要在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

3 个答案:

答案 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();
        }
      }
}

结果将如下:

The result

当您可以访问数据时,可以创建一个新的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;
}
}