【问题标题】:Best way to represent list of XPaths in java在 java 中表示 XPath 列表的最佳方法
【发布时间】:2015-08-23 08:03:42
【问题描述】:

我有一个从模式生成的 XPath 列表,我想在 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"
                                }]
                            }
                        }]
                }]
        }]
}]

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

编辑:这里要求的是代码..

树模型

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]);
        }
    }

编辑:短暂休息后,我以新的视角回到了这个问题。看来这个问题很容易解决!基本上只是用 ArrayList 替换了 HashMap 并添加了几个额外的方法来检查 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;
    }

【问题讨论】:

  • 向我们展示您的“无效”代码..

标签: java json xml xpath jstree


【解决方案1】:

我将使用具有以下属性的 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

【讨论】:

    【解决方案2】:

    如果您使用的是 Java 8,您应该查看我的开源项目:unXmlunXml 基本上是从 Xpath 映射到 Json 属性。

    Maven Central 上可用。使用 > version 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"
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 2018-03-13
      • 2015-05-10
      • 2014-09-30
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 1970-01-01
      相关资源
      最近更新 更多