首页 文章

Java,XPath Expression用于读取所有节点名称,节点值和属性

提问于
浏览
0

我需要帮助来创建一个xpath表达式来读取xml字符串中的所有节点名称,节点值和属性 . 我做的:

private List<String> listOne = new ArrayList<String>();
private List<String> listTwo = new ArrayList<String>();

public void read(String xml) {
    try {
        // Turn String into a Document
        Document document = DocumentBuilderFactory.newInstance()
                .newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes()));

        // Setup XPath to retrieve all tags and values
        XPath xPath = XPathFactory.newInstance().newXPath();
        NodeList nodeList = (NodeList) xPath.evaluate("//text()[normalize-space()='']", document, XPathConstants.NODESET);

        // Iterate through nodes
        for(int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            listOne.add(node.getNodeName());
            listTwo.add(node.getNodeValue());
            // Another list to hold attributes
        }

    } catch(Exception e) {
        LogHandle.info(e.getMessage());
    }
}

我在网上找到了表达式 //text()[normalize-space()=''] ;但是,它不起作用 . 当我尝试从 listOne 获取节点名称时,它只是 #text . 我试过 // ,但这也不起作用 . 如果我有这个XML:

<Data xmlns="Somenamespace.nsc">
    <Test>blah</Test>
    <Foo>bar</Foo>
    <Date id="2">12242016</Date>
    <Phone>
        <Home>5555555555</Home>
        <Mobile>5555556789</Mobile>
    </Phone>
</Data>

listOne[0] 应该保持 DatalistOne[1] 应该保持 TestlistTwo[1] 应该保存 blah 等...所有属性都将保存在另一个并行列表中 .

xPath 应该评估什么表达式?

注意:XML String可以有不同的标签,所以我不能硬编码任何东西 .

Update :试过这个循环:

NodeList nodeList = (NodeList) xPath.evaluate("//*", document, XPathConstants.NODESET);

// Iterate through nodes
for(int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);

    listOne.add(i, node.getNodeName());

    // If null then must be text node
    if(node.getChildNodes() == null)
        listTwo.add(i, node.getTextContent());
}

但是,这只获取根元素 Data ,然后才停止 .

1 回答

  • 1

    //* 将选择所有元素节点, //@* 所有属性节点 . 但是,元素节点在DOM中没有有意义的节点值,因此您需要读出 getTextContent() 而不是 getNodeValue .

    由于您似乎认为具有子元素的元素具有“null”值,我认为您需要检查是否存在任何子元素:

    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        docBuilderFactory.setNamespaceAware(true);
    
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    
        Document doc = docBuilder.parse("sampleInput1.xml");
    
        XPathFactory fact = XPathFactory.newInstance();
        XPath xpath = fact.newXPath();
    
        NodeList allElements = (NodeList)xpath.evaluate("//*", doc, XPathConstants.NODESET);
    
        ArrayList<String> elementNames = new ArrayList<>();
        ArrayList<String> elementValues = new ArrayList<>();
    
        for (int i = 0; i < allElements.getLength(); i++)
        {
            Node currentElement = allElements.item(i);
            elementNames.add(i, currentElement.getLocalName());
            elementValues.add(i, xpath.evaluate("*", currentElement, XPathConstants.NODE) != null ? null : currentElement.getTextContent());
        }
    
        for (int i = 0; i < elementNames.size(); i++)
        {
            System.out.println("Name: " + elementNames.get(i) + "; value: " + (elementValues.get(i)));
        }
    

    对于样本输入

    <Data xmlns="Somenamespace.nsc">
        <Test>blah</Test>
        <Foo>bar</Foo>
        <Date id="2">12242016</Date>
        <Phone>
            <Home>5555555555</Home>
            <Mobile>5555556789</Mobile>
        </Phone>
    </Data>
    

    输出是

    Name: Data; value: null
    Name: Test; value: blah
    Name: Foo; value: bar
    Name: Date; value: 12242016
    Name: Phone; value: null
    Name: Home; value: 5555555555
    Name: Mobile; value: 5555556789
    

相关问题