簡體   English   中英

在Java中表示XPath列表的最佳方法

[英]Best way to represent list of XPaths in java

我有一個列表,這些列表是根據我想在Java對象中按層次表示的模式生成的。 基本上,我想從XPath拆分每個“ /”,並將它們視為單獨的對象,沒有重復項。 目前,我已將列表加載到具有包含子對象的HashMap的對象中。

我想做類似的事情,但改用ArrayList。 這是因為我想生成一個沒有HashMap鍵的JSON字符串。 該消息將用於顯示樹視圖(使用jstree)。

輸入:

Root/Customers/Customer/CompanyName
Root/Customers/Customer/ContactName
Root/Customers/Customer/ContactTitle
Root/Customers/Customer/Phone
Root/Customers/Customer/Fax
Root/Customers/Customer/FullAddress/Address
Root/Customers/Customer/FullAddress/City
Root/Customers/Customer/FullAddress/Region
Root/Customers/Customer/FullAddress/PostalCode
Root/Customers/Customer/FullAddress/Country
Root/Orders/Order/CustomerID
Root/Orders/Order/EmployeeID
Root/Orders/Order/OrderDate
Root/Orders/Order/RequiredDate
Root/Orders/Order/ShipInfo/ShipVia
Root/Orders/Order/ShipInfo/Freight
Root/Orders/Order/ShipInfo/ShipName
Root/Orders/Order/ShipInfo/ShipAddress
Root/Orders/Order/ShipInfo/ShipCity
Root/Orders/Order/ShipInfo/ShipRegion
Root/Orders/Order/ShipInfo/ShipPostalCode
Root/Orders/Order/ShipInfo/ShipCountry

這是我當前的輸出:

{
    "text": "Root",
    "children": {
        "Root": {
            "text": "Root",
            "children": {
                "Orders": {
                    "text": "Orders",
                    "children": {
                        "Order": {
                            "text": "Order",
                            "children": {
                                "RequiredDate": {
                                    "text": "RequiredDate"
                                },
                                "ShipInfo": {
                                    "text": "ShipInfo",
                                    "children": {
                                        "ShipName": {
                                            "text": "ShipName"
                                        },
                                        "ShipCity": {
                                            "text": "ShipCity"
                                        },
                                        "ShipAddress": {
                                            "text": "ShipAddress"
                                        },
                                        "ShipVia": {
                                            "text": "ShipVia"
                                        },
                                        "ShipPostalCode": {
                                            "text": "ShipPostalCode"
                                        },
                                        "ShipCountry": {
                                            "text": "ShipCountry"
                                        },
                                        "Freight": {
                                            "text": "Freight"
                                        },
                                        "ShipRegion": {
                                            "text": "ShipRegion"
                                        }
                                    }
                                },
                                "CustomerID": {
                                    "text": "CustomerID"
                                },
                                "EmployeeID": {
                                    "text": "EmployeeID"
                                },
                                "OrderDate": {
                                    "text": "OrderDate"
                                }
                            }
                        }
                    }
                },
                "Customers": {
                    "text": "Customers",
                    "children": {
                        "Customer": {
                            "text": "Customer",
                            "children": {
                                "CompanyName": {
                                    "text": "CompanyName"
                                },
                                "FullAddress": {
                                    "text": "FullAddress",
                                    "children": {
                                        "Address": {
                                            "text": "Address"
                                        },
                                        "Region": {
                                            "text": "Region"
                                        },
                                        "PostalCode": {
                                            "text": "PostalCode"
                                        },
                                        "Country": {
                                            "text": "Country"
                                        },
                                        "City": {
                                            "text": "City"
                                        }
                                    }
                                },
                                "Phone": {
                                    "text": "Phone"
                                },
                                "Fax": {
                                    "text": "Fax"
                                },
                                "ContactName": {
                                    "text": "ContactName"
                                },
                                "ContactTitle": {
                                    "text": "ContactTitle"
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

這是我想要的輸出:

"data": [{
        "text": "Root",
        "children": [{
                "text": "Orders",
                "children": [{
                        "text": "Order",
                        "children": [{
                                "text": "RequiredDate"
                            }, {
                                "text": "ShipInfo",
                                "children": [{
                                    "text": "ShipName"
                                }, {
                                    "text": "ShipCity"
                                }, {
                                    "text": "ShipAddress"
                                }, {
                                    "text": "ShipCity"
                                }, {
                                    "text": "ShipRegion"
                                }, {
                                    "text": "ShipPostcode"
                                }, {
                                    "text": "ShipCountry"
                                }]
                            }
                        }]
                }]
        }]
}]

是否有人對實現此目標的最佳方法有任何想法? 感謝任何答案!

編輯:按要求這里是代碼..

的TreeModel

public class TreeNode {

    String id;
    String text;
    HashMap<String, TreeNode> children;

    public TreeNode(String text)
    {
        this.text = text;

    }

    @Override
    public String toString() {
        return "TreeModel [id=" + id + ", text=" + text + ", children="
                + children + "]";
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public HashMap<String, TreeNode> getChildren() {
        return children;
    }

    public void setChildren(HashMap<String, TreeNode> children) {
        this.children = children;
    }
}

編碼

 File file = new File("xpaths.txt");

        try {
            BufferedReader br = new BufferedReader(new FileReader(file));

            TreeNode root = new TreeNode("Root");

            String currentLine;

            try {
                while((currentLine = br.readLine()) != null)
                {
                    XpathUtils.processXPath(currentLine, root);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }


            System.out.println(new Gson().toJson(root));

XpathUtils

   public static void processXPath(String xpath, TreeNode parent)
    {
        String[] elements = xpath.split("/");

        for(int i=0; i < elements.length; i ++)
        {
            parent = processElement(elements, parent, i);
        }
    }

    private static TreeNode processElement(
            String[] xpath, 
            TreeNode parent,
            int position)
    {
        if(parent.getChildren() == null)
        {
            parent.setChildren(new HashMap<String, TreeNode>());
        }

        if(!parent.getChildren().containsKey(xpath[position]))
        {
            TreeNode element = new TreeNode(xpath[position]);
            parent.getChildren().put(xpath[position], element);
            return element;
        } else {
            return parent.getChildren().get(xpath[position]);
        }
    }

編輯:短暫休息后,我以新的視角回到了問題。 看來問題很容易解決! 基本上只是將HashMap替換為ArrayList,並添加了一些額外的方法來檢查XPath元素是否已添加。 可能不是最有效的方法,因為它每次都會循環數組,但可以設法完成工作。

完成的代碼:

/**
     * Processes an XPath by splitting each element and 
     * adding them into individual @TreeNode objects.
     * 
     * @param xpath The XPath that is being processed
     * @param parent The top level parent @TreeNode 
     */
    public static void processXPath(String xpath, TreeNode parent) {
        String[] elements = xpath.split("/");

        for (int i = 0; i < elements.length; i++) {
            parent = processElement(elements, parent, i);
        }
    }

    /**
     * Add an element of an XPath  array to a @TreeNode object
     * firstly checking if the element already has a corresponding 
     * @TreeNode.
     * 
     * @param xpath The Xpath that is being processed
     * @param parent The parent TreeNode of the xpath element
     * @param position The the element is in the xpath array
     * @return
     */
    private static TreeNode processElement(String[] xpath, TreeNode parent,
            int position) {
        if (parent.getChildren() == null) {
            parent.setChildren(new ArrayList<TreeNode>());
        }

        if (doesNodeExist(xpath[position], parent.getChildren())) {
            return getExistingNode(xpath[position], parent.getChildren());

        } else {
            TreeNode element = new TreeNode(xpath[position]);
            parent.getChildren().add(element);

            return element;
        }
    }

    /**
     * Loop through the parent nodes children and returns a @Boolean
     * depicting if the node has already been added to the @ArrayList
     * 
     * @param element The name of the element that is being processed
     * @param children The list of children from the parent node
     * @return 
     */
    private static boolean doesNodeExist(String element,
            ArrayList<TreeNode> children) {
        for (TreeNode node : children) {
            if (node.getText().equals(element)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Loops through the parent nodes children and returns the 
     * @TreeNode object that was specified
     * 
     * @param element
     * @param children
     * @return
     */
    private static TreeNode getExistingNode(String element,
            ArrayList<TreeNode> children) {
        for (TreeNode node : children) {
            if (node.getText().equals(element)) {
                return node;
            }
        }

        return null;
    }

我將使用具有以下屬性的Node對象創建一個簡單的樹:

String pathElement

boolean isComplete // true if this is a complete path for cases where you have a path a/b and and a path a/b/x a would have this set to false, but b and x will have it set to true

List<Node> children

如果您使用的是Java 8,則應簽出我的開源項目: unXml unXml基本上從Xpaths映射到Json屬性。

它在Maven Central上可用。 使用>版本0.8.1來獲取遞歸內容。

它使用Jackson進行Json處理。 如果需要,Jackson可以優雅地映射到Objects

輸入XML(已簡化,但是Java代碼也可以與您的xml一起使用)

<Root>
    <Orders>
        <Order>
            <CustomerID></CustomerID>
            <EmployeeID></EmployeeID>
        </Order>
    </Orders>
</Root>

Java代碼

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.nerdforge.unxml.Parsing;
import com.nerdforge.unxml.factory.ParsingFactory;
import com.nerdforge.unxml.parsers.Parser;
import org.w3c.dom.Document;

class TreeParser {
    private Parsing parsing = ParsingFactory.getInstance().create();

    /**
     * This method will parse your XML, and return a Json ObjectNode
     */
    public ObjectNode parseXml(String inputXML){
        // get Xml as Document
        Document document = parsing.xml().document(inputXML);

        // create parser    
        Parser<ObjectNode> parser = parsing.obj()
            .attribute("data", "Root", recursiveParser())
            .build();

        return parser.apply(document);
    }

    public Parser<ObjectNode> recursiveParser(){
        return parsing.obj()
            .attribute("text", parsing.simple().nodeNameParser())
            .attribute("children",
                parsing.arr("node()", parsing.with(this::recursiveParser))
            ).build();
    }
}

輸出JSON

{
    "data":{
        "children":[{
            "children":[{
                "children":[{
                    "children":[],
                    "text":"CustomerID"
                },{
                    "children":[],
                    "text":"EmployeeID"
                }],
                "text":"Order"
            }],
            "text":"Orders"
        }],
        "text":"Root"
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM