在Java中表示XPath列表的最佳方法 [英] Best way to represent list of XPaths in java

查看:56
本文介绍了在Java中表示XPath列表的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个列表,这些列表是根据我想在Java对象中分层表示的模式生成的.基本上,我想从XPath拆分每个"/",并将它们视为单独的对象,没有重复项.目前,我已将该列表加载到具有包含子对象的HashMap的对象中.

I have a list of XPaths generated from a schema that I would like to represent hierarchically in Java objects. Basically I want to split each "/" from the XPath and treat them as individual objects, with no duplicates. Currently I have loaded the list into objects that have a HashMap containing the children objects.

我想做类似的事情,但改用ArrayList.这是因为我想生成一个没有HashMap键的JSON字符串.该消息将用于显示树视图(使用jstree).

I want to do something similar but use an ArrayList instead. This is because I want to generate a JSON string without the HashMap keys. The message will be used to display a tree view (using 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"
                                }]
                            }
                        }]
                }]
        }]
}]

有人对实现这一目标的最佳方法有任何想法吗?感谢任何答案!

Does anyone have any ideas on the best way to achieve this? Appreciate any answers!

根据要求,这里是代码.

As requested here is the code..

TreeModel

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

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元素是否已添加.可能不是最有效的方法,因为它每次都会循环数组,但可以设法完成工作.

After a short break I returned to the problem with a new perspective. It seems the problem was pretty easy to fix! Basically just replaced the HashMap with an ArrayList and added a couple of extra methods to check if the XPath element had already been added or not. Probably not the most efficient way as it loops the array each time but it manages to get the job done.

完成代码:

/**
     * 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;
    }

推荐答案

如果您使用的是Java 8,则应查看我的开放源代码项目: unXml . unXml基本上是从Xpath映射到Json属性.

If you are using Java 8, you should check out my Open Source project: unXml. unXml basically maps from Xpaths to Json-attributes.

可以在 Maven Central .使用>版本0.8.1来获取递归的内容.

It's available on Maven Central. Use > version 0.8.1, to get the recursive stuff.

它使用Jackson进行Json处理.杰克逊可以根据需要优雅地映射到Objects.

It uses Jackson for Json handling. And Jackson can elegantly map to Objects if you need it.

输入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"
    }
}

这篇关于在Java中表示XPath列表的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆