2

そのため、HTMLファイルをDOMツリーに解析し、XPath式を介してノードを抽出しようとしています。

HTMLをDOMツリーに正常に解析できますが、XPathを介してノードを抽出しようとすると、何も得られません。

これは関連性のあるコードスニペットにすぎないことに注意してください。

import org.cyberneko.html.parsers.DOMParser;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.DOMReader;
import org.xml.sax.InputSource;

DOMParser parser = new DOMParser();

parser.parse(new InputSource("file:///Z:/homepage.htm"));
org.w3c.dom.Document doc = parser.getDocument();

DOMReader reader = new DOMReader();
Document document = reader.read(doc);

@SuppressWarnings("unchecked")
List<Node> nodes = document.selectNodes("//HEAD/LINK");

ノード=0。

完全を期すために、HTMLのスニペットを次に示します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML xmlns="http://www.w3.org/1999/xhtml">
    <HEAD>
        <META content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
        <TITLE/>
        <LINK
            href="wcm/groups/visual/documents/webasset/####_ie_5_css.css"
            media="all" rel="stylesheet" type="text/css"/>
        <LINK
            href="wcm/groups/visual/documents/webasset/####_ie_5_5000_css.css"
            media="all" rel="stylesheet" type="text/css"/>
        <LINK
            href="wcm/groups/visual/documents/webasset/####_ie_6_css.css"
            media="all" rel="stylesheet" type="text/css"/>

いつものように感謝します、

ジョー

4

2 に答える 2

3

これは名前空間に関連していると思います。

document.selectNodes("//HEAD/LINK");

名前空間を認識する必要があります。例えば

document.selectNodes("//*[local-name()='HEAD']/*[local-name()='LINK']");

XPath2.0は許可します

document.selectNodes("//:HEAD/:LINK");
于 2012-11-30T09:32:29.537 に答える
3

@BrianAgnewは正しいです、あなたの問題は名前空間に関連しています。

問題はここにあります

<HTML xmlns="http://www.w3.org/1999/xhtml">

ドキュメントにはデフォルトの名前空間があるため、要素と要素の両方が デフォルトの名前空間に属しているため、xmlns="http://www.w3.org/1999/xhtml"XPath式は機能しません(xmlns = "http://www.w3.org/1999/xhtml")//HEAD/LINKHEADLINK

@BrianAgnewは以下の使用を提案しました:

document.selectNodes("//*[local-name()='HEAD']/*[local-name()='LINK']");

local-name()なぜ機能するのかについての詳細は、を参照してください。

XPATHSとデフォルトの名前空間、および同じスレッドでの回答

local-name()を使用せずにこれらのノードを選択する別の方法があります。それは、デフォルトの名前空間のエイリアスを作成し、それをXPath式で使用することです。

例えば

    Map<String, String> namespaceUris = new HashMap<String, String>();  
    namespaceUris.put("foobar", "http://www.w3.org/1999/xhtml");  

    XPath xPath = DocumentHelper.createXPath("//foobar:HEAD/foobar:LINK");  
    xPath.setNamespaceURIs(namespaceUris);  

    @SuppressWarnings("unchecked")
    List<Nodes> selectNodes = xPath.selectNodes(document);

上記では、エイリアスfoobarをhttp://www.w3.org/1999/xhtmlデフォルトの名前空間と同じURI()に設定しました。これにより、次のようなxp​​ath式が可能になります。

//foobar:HEAD/foobar:LINKもちろん、機能するために、好きなエイリアスを使用できます。

これは両方のアプローチを使用するサンプルアプリです。少しラフですが、正しいアイデアが得られるはずです。

package org.foo.bar.foobar;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nu.xom.Nodes;

import org.cyberneko.html.parsers.DOMParser;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;
import org.dom4j.XPath;
import org.dom4j.io.DOMReader;
import org.dom4j.io.XMLWriter;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class App 
{
    public static void main( String[] args ) throws SAXException, IOException
    {

        DOMParser parser = new DOMParser();

        parser.parse(new InputSource("file:///Z:/homepage.htm"));
        org.w3c.dom.Document doc = parser.getDocument();

        DOMReader reader = new DOMReader();
        Document document = reader.read(doc);

        XMLWriter xmlWriter = new XMLWriter(System.out);
        xmlWriter.write(document);

        @SuppressWarnings("unchecked")

        List<Node> nodes = document.selectNodes("//*[local-name()='HEAD']/*[local-name()='LINK']");
        System.out.println("Number of Nodes: " +nodes.size());

        Map<String, String> namespaceUris = new HashMap<String, String>();  
        namespaceUris.put("foobar", "http://www.w3.org/1999/xhtml");  

        XPath xPath = DocumentHelper.createXPath("//foobar:HEAD/foobar:LINK");  
        xPath.setNamespaceURIs(namespaceUris);  

        @SuppressWarnings("unchecked")
        List<Nodes> selectNodes = xPath.selectNodes(document);
        System.out.println("Number of nodes: " +selectNodes.size());

    }
}

これが私がよく使ったpomです

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.foo.bar</groupId>
    <artifactId>foobar</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>foobar</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.6.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

また、One Fork、XML名前空間でDom4J XPathを使用する方法も参照してください。これは、遭遇した状況と非常によく似た状況をカバーしています。

于 2012-12-03T23:23:04.610 に答える