2012-08-03 12 views
19

Jest to ważny XPath w JavaScript:Przekształć JavaScript XPath w poprawnym zapytaniu PHP() XPath | normalizować JS XPath -> PHP

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

I okazało się ważnym PHP XPath do stosowania z DOMXPath-> zapytanie() jest

//*[@id="priceInfo"]//div[@class="standardProdPricingGroup"]//span[1] 
  1. znasz jakieś biblioteki lub niestandardowe komponenty, które już wykonują tę transformację?
  2. Czy znasz dostępną dokumentację zawierającą dwie różnice w składni?

Moim głównym zmartwieniem jest to, że może istnieć wiele różnic, a ja staram się zidentyfikować te różnice i mam problemy z ich identyfikacją.

Pytanie może być również przedstawione w inny sposób: Ponieważ JavaScript może mieć różne prawidłowe formaty XPath, jak je normalizować, aby działały z PHP.

Jedna z aktualizacji wspomina również, że funkcja id() jest poprawna XPath, jeśli istnieje poprawny DTD, który zawiera tę definicję. Nie mam władzy nad DTD wejścia i jeśli istnieje sposób na znalezienie rozwiązania, które działa bez określonego DTD, byłoby super.

Aktualizacja:

Chcę przekształcić pierwszego formatu na drugi za pomocą algorytmu. Moje wejście jest pierwsze, a nie drugie. Nie można tego zmienić.

Jak zaznaczył @Nison Maël, drugi format jest prawidłowy Javascript XPath, jak przedstawiono tutaj: http://jsbin.com/elatum/2/edit to niestety tylko powiększa problem fragmentacji JavaScript XPath.

@sathe wskazał, że poprawna kwerenda JavaScript XPath działa dobrze w PHP, jeśli dane wejściowe udokumentowane mają poprawny DTD (@Dimitre Novatchev wspomniał o tym w komentarzu, ale przeoczył znaczenie). Niestety nie mam kontroli nad DTD wejścia, więc teraz muszę zbadać sposób na pokonanie tego, lub znaleźć rozwiązanie, które działa nawet bez ważnego DTD.

+1

To jest świetne pytanie! Wygląda na to, że nie ma tam żadnej dokumentacji (przynajmniej nie przez pobieżne wyszukiwanie w Google). Jestem podekscytowany, widząc odpowiedź na tę. – Matt

+0

Pierwsze wyrażenie jest prawnym wyrażeniem XPath. Jednakże, aby funkcja Xpath "id()' działała, XML musi mieć DTD, a definicje elementów w DTD muszą mieć atrybuty, które mają słowo kluczowe "ID". –

+0

@DimitreNovatchev: A co z tłumaczeniem '//' na '/'? – choroba

Odpowiedz

7

Tylko widząc, że Salathe faktycznie odpowiedział tym samym, ale biorąc pod uwagę swój komentarz i podkreślić to nieco więcej:

Nie trzeba podać dowolny DTD. Dopóki używasz funkcji DOMDocument::loadHTML lub DOMDocument::loadHTMLFile, atrybut HTML id jest zarejestrowany dla funkcji xpath id(). Z HTML demo podanej w http://jsbin.com/elatum/2/edit, nawet się błąd podczas ładowania dokumentu:

Warning: DOMDocument :: loadHTMLFile(): ID priceInfo już zdefiniowane w ...

Który już jest znakiem, że jest to prawdziwy atrybut identyfikatora, ponieważ on jęczy o duplikatach.A related przykładowy kod wygląda następująco:

$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"; 
} 

Wyjście jest:

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

W przypadku trzeba większą kontrolę, najpierw uruchomić XPath aby oznaczyć wszystkie HTML id atrybuty jak identyfikator dla XPath:

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

Następnie można użyć tej samej ścieżki xpath z funkcją id(), nie trzeba jej zmieniać.

0

Nie możesz po prostu przetłumaczyć id("...") na //*[@id="..."][1] na początku wyrażenia?

Na przykład, jeśli można założyć, że nie będzie miał żadnych nawiasie przy id(...) wyrażeń:

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

Sample code

edit: poprawione wymiany, ID() imust jako pierwszy w wyrażeniu

+0

To pomaga, ale jestem ciekaw, jakie inne nieudokumentowane rzeczy mogą pojawić się w przyszłości. – Pentium10

+1

To naprawdę nieudokumentowane rzeczy, specyfikacje XPATH są dość jasne o tym zachowaniu. Część nieudokumentowana dotyczy mechanizmu DOM przeglądarki, który domyślnie stosuje Doctype do HTML DOM. –

+1

@ Pentium10 Być może musisz być bardziej konkretny o tym, co próbujesz osiągnąć. –

0

To nie jest pełna odpowiedź, ale jest zbyt duża, aby ją skomentować i może ci w tym pomóc.

Jeśli masz kontrolę nad XML wejściowego, a następnie zamiast używać DTD zadeklarować id atrybuty, można zadeklarować je wyraźnie w dokumencie XML samego poprzedzając id atrybuty z xml:.

Na przykład, jeśli miał XML z

<foo id="x27"/> 

i zmienił je na

<foo xml:id="x27"/> 

wówczas funkcja id(), by uznać, że atrybut jako formalny XML id typu, nie tylko jako atrybut o nazwie id.

Wiem, że ta "sztuczka" działa na procesorze Saxon, ale muszę przyznać, że nie próbowałem go z PHP.

W3C xml:id

+0

PHP ["DOMElement :: setIdAttribute"] (http://de.php.net/DOMElement.setIdAttribute) pozwala na określenie nazwy atrybutu 'xml: id' bez względu na dane wejściowe (i bez zmian to). Przykład znajduje się w [moja odpowiedź] (http://stackoverflow.com/a/11819341/367456) – hakre