2011-01-12 12 views
5

Próbuję napisać XPath, który wybierze określone węzły, które zawierają określone słowo. W tym przypadku słowo to "Lockwood". Prawidłowa odpowiedź to 3. Obie te ścieżki dać mi 3.XSLT Wybierz wszystkie węzły zawierające określony podłańcuch

count(//*[contains(./*,'Lockwood')]) 
count(BusinessLetter/*[contains(../*,'Lockwood')]) 

Ale przy próbie wyjścia tekst każdego konkretnego węzła

//*[contains(./*,'Lockwood')][1] 
//*[contains(./*,'Lockwood')][2] 
//*[contains(./*,'Lockwood')][3] 

Node 1 kończy się zawierające cały tekst i węzły 2 i 3 są puste.

Czy ktoś może mi powiedzieć, co się dzieje lub co robię źle.

Dzięki.

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="XPathFunctions.xsl"?> 
<BusinessLetter> 
<Head> 
    <SendDate>November 29, 2005</SendDate> 
    <Recipient> 
    <Name Title="Mr."> 
    <FirstName>Joshua</FirstName> 
    <LastName>Lockwood</LastName> 
    </Name> 
    <Company>Lockwood &amp; Lockwood</Company> 
    <Address> 
    <Street>291 Broadway Ave.</Street> 
    <City>New York</City> 
    <State>NY</State> 
    <Zip>10007</Zip> 
    <Country>United States</Country> 
    </Address> 
    </Recipient> 
</Head> 
<Body> 
    <List> 
    <Heading>Along with this letter, I have enclosed the following items:</Heading> 
    <ListItem>two original, execution copies of the Webucator Master Services Agreement</ListItem> 
    <ListItem>two original, execution copies of the Webucator Premier Support for Developers Services Description between Lockwood &amp; Lockwood and Webucator, Inc.</ListItem> 
    </List> 
    <Para>Please sign and return all four original, execution copies to me at your earliest convenience. Upon receipt of the executed copies, we will immediately return a fully executed, original copy of both agreements to you.</Para> 
    <Para>Please send all four original, execution copies to my attention as follows: 

<Person> 
    <Name> 
    <FirstName>Bill</FirstName> 
    <LastName>Smith</LastName> 
    </Name> 
    <Address> 
    <Company>Webucator, Inc.</Company> 
    <Street>4933 Jamesville Rd.</Street> 
    <City>Jamesville</City> 
    <State>NY</State> 
    <Zip>13078</Zip> 
    <Country>USA</Country> 
    </Address> 
    </Person> 
    </Para> 
    <Para>If you have any questions, feel free to call me at <Phone>800-555-1000 x123</Phone> or e-mail me at <Email>[email protected]</Email>.</Para> 
</Body> 
<Foot> 
    <Closing> 
    <Name> 
    <FirstName>Bill</FirstName> 
    <LastName>Smith</LastName> 
    </Name> 
    <JobTitle>VP of Operations</JobTitle> 
    </Closing> 
</Foot> 
</BusinessLetter> 
+0

Dobre pytanie, +1. Zobacz moją odpowiedź na wyjaśnienia, kompletne i łatwe rozwiązanie oraz przydatną regułę do zapamiętania. :) –

Odpowiedz

10

Ale gdy próbuję do wyprowadzenia tekst każdy konkretny węzeł

//*[contains(./*,'Lockwood')][1] 
//*[contains(./*,'Lockwood')][2] 
//*[contains(./*,'Lockwood')][3] 

Node 1 kończy się zawierające cały tekst i węzły 2 i 3 są puste

To jest często zadawane pytania.

//SomeExpression[1] 

nie jest równoznaczne z

(//someExpression)[1] 

byłego wybiera wszystkie //SomeExpression węzły, które są pierwszym dzieckiem swojego rodzica.

Ten drugi wybiera pierwsze (w kolejności dokumentów) wszystkie węzły //SomeExpression w całym dokumencie.

Jak to ma zastosowanie do problemu?

//*[contains(./*,'Lockwood')][1] 

ten wybiera wszystkie elementy, które mają co najmniej jedno dziecko, którego wartość zawiera ciąg „Lockwood” i że są to pierwsze takie dziecko od rodzica. Wszystkie trzy elementy, które mają węzeł tekstowy zawierający ciąg "Lockwood", są pierwszym takim dzieckiem ich rodziców, więc wynikiem jest wybranie trzech elementów.

//*[contains(./*,'Lockwood')][2] 

Nie ma elementu, który ma dziecko z wartością ciągu zawierającego ciąg "Lockwood" i jest drugim takim dzieckiem swojego rodzica. Nie wybrano żadnych węzłów.

//*[contains(./*,'Lockwood')][3] 

Nie ma elementu, który ma dziecko z wartości ciągu zawierającego ciąg „Lockwood” i jest trzecim takim dzieckiem swojego rodzica. Nie wybrano żadnych węzłów.

Rozwiązanie:

Zastosowanie:

(//*[contains(./*,'Lockwood')])[1] 
(//*[contains(./*,'Lockwood')])[2] 
(//*[contains(./*,'Lockwood')])[3] 

Każdy z tych wybiera dokładnie ty element (N = {1,2,3}) wybrany //*[contains(./*,'Lockwood')] odpowiednio: BusinesLetter, Recipient i Body.

Pamiętaj:

[] operator ma wyższy priorytet (pierwszeństwo) niż skrótem //.

+1

+1 Dobra odpowiedź. Formaly from http://www.w3.org/TR/xpath/#NT-Predicate: * Predykat filtruje zestaw węzłów w odniesieniu do osi, aby wytworzyć nowy zestaw węzłów *. I to '// * [1]' zostaje rozszerzone na '/ descendant-or-self :: node()/child :: * [1] –

Powiązane problemy