简体   繁体   中英

How to remove/stripp off unique text from a Map of Strings Java

I've got a Map<String,list<String>> data structure in which the Key has the following string text:

/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[69]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[70]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[71]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[72]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[73]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[74]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[75]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[76]/PeriodBeginDate[1]

The index numbers represent the current occurrence of that particular element node. However I would like to remove the indexes for the elements for which there is only 1 occurance.

Example:

From:

/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[69]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[70]/PeriodBeginDate[1]

To:

/PayrollFormInfo/CompanyInfo/FederalTotals[69]/PeriodBeginDate
/PayrollFormInfo/CompanyInfo/FederalTotals[70]/PeriodBeginDate

How can I do this in Java

Edit:

@Andreas brings up a good point. My current implementation for getting an indexed XPath is here:

public String getFullXPath(Node n) {
    if (null == n)
        return null;

    Node parent;
    Stack<Node> hierarchy = new Stack<Node>();
    StringBuilder builder = new StringBuilder();

    hierarchy.push(n);

    switch (n.getNodeType()) {
        case Node.ATTRIBUTE_NODE:
            parent = ((Attr) n).getOwnerElement();
            break;
        case Node.ELEMENT_NODE:
            parent = n.getParentNode();
            break;
        case Node.DOCUMENT_NODE:
            parent = n.getParentNode();
            break;
        default:
            throw new IllegalStateException("Unexpected Node type" + n.getNodeType());
    }

    while (null != parent
            && parent.getNodeType() != Node.DOCUMENT_NODE
            && !parent.getNodeName().equals("section")) {
        hierarchy.push(parent);
        parent = parent.getParentNode();
    }

    Object obj;
    while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
        Node node = (Node) obj;

        if (node.getNodeType() == Node.ELEMENT_NODE) { 
            builder.append("/").append(node.getNodeName());

            int prev_siblings = 1;
            Node prev_sibling = node.getPreviousSibling();

            while (null != prev_sibling) {
                if (prev_sibling.getNodeType() == node.getNodeType()) {
                    if (prev_sibling.getNodeName().equalsIgnoreCase(node.getNodeName())) {
                        prev_siblings++;
                    }
                }
                prev_sibling = prev_sibling.getPreviousSibling();
            }
            builder.append("[").append(prev_siblings).append("]");
        } 

        else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            builder.append("/@");
            builder.append(node.getNodeName());
        }
    }

    return builder.toString();
}

Edit:

Added if() {} else conditional as per @Andreas solution but I am not getting my output with indexes as all [1]'s?

        if (node.getNodeType() == Node.ELEMENT_NODE) { 
            builder.append("/").append(node.getNodeName());

            int prev_siblings = 1;
            Node prev_sibling = node.getPreviousSibling();

            while (null != prev_sibling) {
                if (prev_sibling.getNodeType() == node.getNodeType()) {
                    if (prev_sibling.getNodeName().equalsIgnoreCase(node.getNodeName())) {
                        prev_siblings++;
                    }
                }
                prev_sibling = prev_sibling.getPreviousSibling();
            }
            // edit Outside the while loop
            if(prev_siblings == 1 && node.getNextSibling() == null) {
                continue;
            } else builder.append("[").append(prev_siblings).append("]");
        } 

Now my output is:

/PayrollFormInfo/PaidPreparerInfo[1]/Address1[1]
/PayrollFormInfo/PaidPreparerInfo[1]/City[1]
/PayrollFormInfo/PaidPreparerInfo[1]/State[1]
/PayrollFormInfo/PaidPreparerInfo[1]/Zip[1]

Looks like your method works but only for the root element.

One approach could be to remove the ' 1 ' from the string before placing it in the Map. Something like this

Map<String,list<String>> myMap = new HashMap<String,list<String>>();
//lets say variable 'k' has the key and another list v which has value
String k = "/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[69]/PeriodBeginDate[1]";
myMap.put(k.replace("[1]",""), v);

Further details on replace function: String replace() method

First, you'd have to identify that you only have 1 occurrence. Example:

/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[70]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[71]/PeriodBeginDate[1]
/PayrollFormInfo[1]/CompanyInfo[1]/FederalTotals[71]/PeriodBeginDate[2]

Here, PeriodBeginDate for FederalTotals 70 is singular, but PeriodBeginDate for FederalTotals 71 is not.

You current storage mechanism makes it extremely difficult to know which can be "shortened".

You need to build a hierarchy structure for your keys, so you can check the "child count" of any node in the hierarchy.

Rather than adding the number when building your first map, build up your data using the new hierarchy structure, and construct the "path" when needed.

Using regex and replaceAll:

str = str.replaceAll("\\[1\\]", "");


Userful links:

Regex Java Tester Online

JavaSE String.replaceAll

With the addition of getFullXPath to the question, the solution is fairly simple.

The method is counting the number of "previous siblings" (+1) to know the number to assign. If that number is 1, check if it has a "next sibling", and don't add the number if it doesn't.

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