简体   繁体   中英

How to group elements with similar attribute id of the parent tag in SAX parser [Java]

Sample of the xml:

<name>item1</name>
<reference_id>100</reference_id> -->notice of the duplicate reference id

<name>item 2</name>
<reference_id>200</reference_id>

<name>item 3</name>
<reference_id>100</reference_id> -->notice of the duplicate reference id

<name>item 4</name>
<reference_id>400</reference_id>

I have a large xml file which I use SAX Parser to extract data according to the element tag but since SAX Parser does not follow hierachy and each element attribute or tag is purely identified and added in the respective arraylist.

Current Output:

name: [item 1, item 2, item 3, item 4]

reference_id :[100, 200, 100, 400]

Current Problem:

I want to create a method when user inputs a keyword and is able to display the result.

Eg if user enters item 1 as the keyword, my idea is to get the position of the keyword in name arraylist and retreive the same position from arraylist reference id since it is one to one match. So in this case is name[0] = reference_id[0].

But the problem is when I do a filtering of the reference id as keyword. How can reference id tells which name it is linked to? Supposely if all reference id is distinct, there should not have any problem. But notice there is duplicated id. How should I go about doing it?

There are two concepts you can apply for this.

Concept 1 use a Default Handler

You can parse your XML using a handler, as the handler process each node you will need to build the objects you want using the start and end element methods.

The object I will store the data in called Name

public class Name
{
  private String name = null;
  private String value = null;

  public String getName()
  {
    return name;
  }

  public void setName(String name)
  {
    this.name = name;
  }

  public String getValue()
  {
    return value;
  }

  public void setValue(String value)
  {
    this.value = value;
  }
}

The default handler class

public class NameHandler extends DefaultHandler
{
  private ArrayList<Name> nameList;
  private Name name = null;
  private boolean nameTag = false;
  private boolean valueTag = false;


  @Override
  public void startElement(String uri, String localName, String qName, Attributes attributes)
          throws SAXException
  {

    if (qName.equalsIgnoreCase("name"))
    {
      name = new Name();
      nameTag = true;
    }
    if (qName.equalsIgnoreCase("reference_id"))
    {
      valueTag = true;
    }
  }

  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException
  {
    if (qName.equalsIgnoreCase("name"))
    {
      //add Name object to list
      nameList.add(name);         
    }
  }

  @Override public void characters(char[] ch, int start, int length) throws SAXException
  {
    String theValue = new String(ch, start, length);
    if (nameTag)
    {
      name.setName(theValue);
      nameTag = false;
    }
    if (valueTag)
    {
      name.setValue(theValue);
      valueTag= false;
    }
  }

  public ArrayList<Name> getNameList()
  {
    return nameList;
  }
}

the code to call all of this is simply

SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
NameHandler handler = new NameHandler();
saxParser.parse(XML,handler);

Concept 2 XML Path using a XML Document

NOTE this is NOT SAX

The XML path can be built and supped by the input being

String expression = "/root[name='item 2']/reference_id";

NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
   System.out.println(nodeList.item(i).getFirstChild().getNodeValue()); 
}

Note completely untested code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM