1

jQuery Xpathプラグインを使用して、HTML ドキュメントの階層をブラウズします。特定の要素への Xpath を通知するサーバー側フレームワークの情報を処理する必要があるため、セレクターは使用しません。

ここで、DOM が必ずしも HTML ドキュメントの階層を表すとは限らないことに気付き、この問題の解決策をここで見つけました. これは、たとえば、HTML ドキュメントに次のコードが含まれている場合を意味します。

<table>
  <tr>
    <td>Hello</td>
  </tr>
</table>

私のDOMは後者を次のように表します:

<table>
  <tbody>
    <tr>
      <td>Hello</td>
    </tr>
  </tbody>
</table>

私のXpathクエリ

jQuery(document).xpath('//table[1]/tr[1]/td[1]')

したがって、もはや結果は得られません。

DOM 表現の合成要素を回避する方法はありますか? または、合成要素が含まれるように Xpath を調整する方法はありますか? 助けてくれてありがとう。

4

3 に答える 3

1

さて、jQuery の助けを借りて、私のユース ケース シナリオで機能するこの代替 XPath パーサーを作成しました。パーサーは入力によって指定された XPath にとどまろうとしますが、DOM モデルがパスの途中に新しいタグを追加し、パスの残りの部分がこの 1 つの要素にラップされている場合、パーサーはこの追加を認識してこれを含めます単一の要素をパスに追加します。もちろん、これはすべてのユース ケース シナリオで機能するわけではありませんが、私の場合は機能します。たぶん、この解決策は、少なくともいくつかの拡張の後、他の人に役立ちます:

var SloppyXPathParser = (function () {

    function childExists($cursor, element) {
        assertSelection($cursor);
        var $movedCursor = $cursor.children(element.name);
        if ($movedCursor.size() > element.index) {
            return jQuery($movedCursor.get(element.index));
        } else if ($cursor.children().size() == 1) {
            return childExists(jQuery($cursor.children().get(0)), element);
        } else {
            throw 'Cannot browse to \'' + element.name + '\' at index ' + element.index + '\'';
        }
    }

    function assertSelection($cursor) {
        if (!($cursor instanceof jQuery) || $cursor.size() != 1) {
            throw 'Selection is invalid: ' + $cursor.size();
        }
    }

    function parsePath(rawPath) {
        var nodes = rawPath.split('/');
        var regex = new RegExp('([a-zA-Z]+)\\[([0-9]+)\\]');
        var elements = [];
        var index = 0;
        jQuery(nodes).each(function (key, element) {
            if (element.length == 0) {
                return true;
            }
            if (!regex.test(element)) {
                throw 'Path element does not match regex: ' + element;
            }
            var matched = regex.exec(element);
            elements[index++] = { name: matched[1], index: matched[2] };
        });
        return elements;
    }

    function findElement(input) {

        var elements = parsePath(input);
        var $cursor = jQuery(document);
        jQuery(elements).each(function (key, element) {
            $cursor = childExists($cursor, element);
        });

        try {
            assertSelection($cursor);
        } catch (cause) {
            console.log('Exception: ' + cause);
            return false;
        }

        return $cursor.get(0);
    }

    return {
        find: function (input) {
            return findElement(input);
        }
    }
})();

var input = '/html[0]/body[0]/table[0]/tr[1]/td[1]';
SloppyXPathParser.find(input);

HTMLソースは次のとおりです。

<html>
  <body>
    <table>
      <tr>
        <td>wrong</td>
        <td>wrong</td>
      </tr>
      <tr>
        <td>wrong</td>
        <td>right</td>
      </tr>
  </table>
  </body>
</html>

tbodyブラウザがDOM に要素を追加することを Firebug などで確認できます。パーサーはこれを認識し、エントリをスキップします。

于 2013-07-18T08:25:47.360 に答える
0

あなたのシングル/をダブルに変えるだけですtr

//table[1]/tr[1]/td[1]->//table[1]//tr[1]/td[1]

これは、最初のテーブル タグの下の任意の深さのテーブル行に一致するため、<tbody>好きなだけタグを追加できます。

于 2013-07-18T09:11:40.603 に答える