2012-08-03 32 views
19

Đây là XPath hợp lệ trong Javascript:Chuyển đổi Javascript XPath trong truy vấn PHP hợp lệ() XPath | bình thường hóa JS XPath -> PHP

id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1] 

Và điều này trở thành hợp lệ PHP XPath để được sử dụng với DOMXPath-> query() là

//*[@id="priceInfo"]//div[@class="standardProdPricingGroup"]//span[1] 
  1. Bạn có biết bất kỳ thư viện hoặc thành phần tùy chỉnh nào đã thực hiện chuyển đổi này không?
  2. bạn có biết tài liệu có sẵn liệt kê hai khác biệt cú pháp không?

Mối quan tâm chính của tôi là có thể có nhiều khác biệt và tôi đang tìm cách xác định những khác biệt này và tôi có vấn đề để xác định những điều này.

Câu hỏi có thể được đặt theo cách khác: Vì Javascript có thể có các định dạng XPath hợp lệ khác nhau, cách bình thường hóa chúng để làm việc với PHP.

Một trong các bản cập nhật cũng đề cập đến hàm id() là XPath hợp lệ nếu có DTD hợp lệ chứa định nghĩa này. Tôi không có quyền lực trên đầu vào DTD, và nếu có một cách để tìm một giải pháp mà làm việc mà không có bất kỳ DTD cụ thể nó sẽ là tuyệt vời.

Cập nhật:

Tôi muốn chuyển đổi định dạng đầu vào thứ hai với một thuật toán. Đầu vào của tôi là cái đầu tiên và không phải cái thứ hai. Không thể thay đổi điều này.

Như @Nison Maël đã chỉ ra, định dạng thứ 2 là Javascript XPath hợp lệ như được trình bày ở đây: http://jsbin.com/elatum/2/edit không may này chỉ thêm vào vấn đề của Javascript "XPath" phân mảnh.

@salathe chỉ ra rằng truy vấn Javascript XPath hợp lệ hoạt động tốt trong PHP nếu tài liệu đầu vào có DTD hợp lệ (@Dimitre Novatchev đã đề cập đến điều này trong nhận xét nhưng bỏ qua tầm quan trọng). Thật không may tôi không có quyền kiểm soát của DTD đầu vào, vì vậy bây giờ tôi phải điều tra một cách để khắc phục điều này, hoặc để tìm một giải pháp mà làm việc ngay cả khi không có DTD hợp lệ.

+1

Đây là một câu hỏi hay! Nó không giống như có bất kỳ tài liệu nào ra khỏi đó (ít nhất là không thông qua một tìm kiếm google cursory). Tôi rất vui khi thấy câu trả lời cho câu hỏi này. – Matt

+0

Biểu thức đầu tiên là biểu thức XPath hợp pháp. Tuy nhiên, để hàm Xpath 'id()' hoạt động, XML phải có một định nghĩa DTD và phần tử trong DTD phải có các thuộc tính có từ khóa 'ID'. –

+0

@DimitreNovatchev: Và về bản dịch của '//' thành '/' thì sao? – choroba

Trả lời

7

Chỉ cần thấy rằng Salathe thực sự trả lời giống nhau, nhưng tham gia bình luận của bạn vào tài khoản và để nhấn mạnh điều này một chút:

Bạn không cần phải chỉ định bất kỳ DTD. Miễn là bạn sử dụng các hàm DOMDocument::loadHTML hoặc DOMDocument::loadHTMLFile, thuộc tính HTML id thực sự được đăng ký cho hàm xpath id(). Với HTML bản demo được đưa ra trong http://jsbin.com/elatum/2/edit, thậm chí bạn nhận được một lỗi khi bạn tải tài liệu:

Cảnh báo: DOMDocument :: loadHTMLFile(): ID priceInfo đã được xác định trong ...

Đó là đã là một dấu hiệu cho thấy đây là thuộc tính ID thực bởi vì nó rên rỉ về các bản sao.Một mẫu mã liên quan trông giống như:

$xpath = 'id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]'; 

$doc = new DOMDocument(); 
$doc->loadHTMLFile(__DIR__ . '/../data/file-11796340.html'); 
$xp = new DOMXPath($doc); 

$r = $xp->query($xpath); 
echo $xpath, "\n"; 
echo $r ? $r->length : 0, ' elements found', "\n"; 
if (!$r) return; 
foreach($r as $node) { 
    echo " - ", $node->nodeValue, "\n"; 
} 

Đầu ra là:

id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1] 
1 elements found 
- hello 

Trong trường hợp bạn cần kiểm soát nhiều hơn, lần đầu tiên chạy một xpath để đánh dấu id thuộc tính như ID tất cả HTML cho xpath:

$r = $xp->query("//*[@id]"); 
if ($r) foreach($r as $node) { 
    $node->setIdAttribute('id', true); 
} 

Sau đó, bạn có thể sử dụng cùng một đường nối với chức năng id(), không cần phải thay đổi nó.

0

Bạn không thể dịch id("...") thành //*[@id="..."][1] khi bắt đầu biểu thức?

Ví dụ, nếu có thể giả định bạn sẽ không có bất kỳ dấu ngoặc trong biểu thức id(...):

$queryRewritten = preg_replace('/^id\(([^\)]+)\)/','//*[@id=$1][1]',$query); 

Sample code

EDIT: sửa thay thế, id() imust là người đầu tiên trong biểu thức

+0

Nó giúp, nhưng tôi tò mò những thứ không có giấy tờ khác có thể đưa ra trong tương lai. – Pentium10

+1

Nó không thực sự không có giấy tờ, thông số XPATH khá rõ ràng về hành vi này. Phần không có giấy tờ về công cụ DOM của trình duyệt ngầm áp dụng một Doctype cho DOM HTML. –

+1

@ Pentium10 Có thể bạn cần phải rõ ràng hơn về những gì bạn đang cố gắng đạt được –

0

Đây không phải là câu trả lời đầy đủ nhưng nó quá lớn để đặt làm nhận xét và có thể giúp bạn một chút.

Nếu bạn có quyền kiểm soát XML đầu vào, thay vì sử dụng DTD để khai báo thuộc tính id, bạn có thể khai báo rõ ràng trong tài liệu XML bằng cách thêm tiền tố id với xml:.

Ví dụ, nếu bạn có XML của

<foo id="x27"/> 

và thay đổi nó để

<foo xml:id="x27"/> 

thì id() chức năng có thể nhận ra thuộc tính đó như là một hình thức XML id loại, không chỉ là thuộc tính có tên id.

Tôi biết "mẹo" này hoạt động trên bộ xử lý Saxon, nhưng tôi phải thừa nhận là tôi đã không thử nó với PHP.

W3C xml:id

+0

['DOMElement :: setIdAttribute'] của PHP (http://de.php.net/DOMElement.setIdAttribute) cho phép chỉ định tên của thuộc tính' xml: id' bất kể đầu vào (và không thay đổi nó). Một ví dụ là trong [câu trả lời của tôi] (http://stackoverflow.com/a/11819341/367456) – hakre