首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何按属性对java中的xml元素进行分组

如何按属性对java中的xml元素进行分组
EN

Stack Overflow用户
提问于 2015-11-19 21:49:24
回答 3查看 2K关注 0票数 2

我要求在Java中对具有相同属性的XML元素进行分组。

下面是我更新后的输入:

代码语言:javascript
复制
<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>

我需要如下输出:

代码语言:javascript
复制
 <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>

我尝试了下面这样的方法:

代码语言:javascript
复制
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

EN

回答 3

Stack Overflow用户

发布于 2015-11-19 22:41:56

首先,您的XML文件不是格式良好的。这是格式良好的版本:

代码语言:javascript
复制
<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文件中的数据:

代码语言:javascript
复制
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文件。

票数 0
EN

Stack Overflow用户

发布于 2015-11-20 19:36:53

正如我在评论中所说的,我认为这对于XSLT2.0(例如使用来自http://mvnrepository.com/artifact/net.sf.saxon/Saxon-HEhttp://sourceforge.net/projects/saxon/files/Saxon-HE/9.6/SaxonHE9-6-0-7J.zip/download的Saxon9.6HE)和以下XSLT代码来说是一项简单的工作:

代码语言:javascript
复制
<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语言中进行分组,Java8支持它,但是DOM并不是真正正确的数据结构,所以你需要首先构建一个List<Element>,然后是分组和构造,然后是新的DOM:

代码语言:javascript
复制
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());

    }

}
票数 0
EN

Stack Overflow用户

发布于 2015-12-01 21:55:48

感谢您的所有回答,但是我能够使用以下代码进行分组。希望它能帮助其他人寻找同样的东西。

代码语言:javascript
复制
 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;
}
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33805760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档