2010-08-14 4 views
5

Pracuję nad rozwojem XSL i potrzebuję znać odpowiednik NOT IN w XPATH. Prezentuję XML i XSL w najprostszym formacie, który byłby zrozumiały dla wszystkich.Nie jest równoważny w wyrażeniu XPath

<?xml-stylesheet type="text/xsl" href="XSL.xsl"?> 
<Message> 
    <Customers> 
     <Customer pin="06067">1</Customer> 
     <Customer pin="06068">2</Customer> 
     <Customer pin="06069">3</Customer> 
     <Customer pin="06070">4</Customer> 
     <Customer pin="06072">5</Customer> 
    </Customers> 
    <Addresses> 
     <Address pin1="06067">A</Address> 
     <Address pin1="06068">B</Address> 
     <Address pin1="06069">C</Address> 
    </Addresses> 
</Message> 

XSL

<xsl:template match="/Message"> 
    <html> 
     <body> 
      <h4>Existing Customers</h4> 
      <table> 
       <xsl:apply-templates select="//Customers/Customer[@pin = //Addresses/Address/@pin1]"></xsl:apply-templates> 
      </table> 

      <h4>New Customers</h4> 
      <table> 
       <!--This place need to be filled with new customers--> 
      </table> 
     </body> 
    </html> 
</xsl:template> 

<xsl:template match="Customer" name="Customer"> 
    <xsl:variable name="pin" select="./@pin"></xsl:variable> 
    <tr> 
     <td> 
      <xsl:value-of select="."/> 
      <xsl:text> is in </xsl:text> 
      <xsl:value-of select="//Addresses/Address[@pin1=$pin]"/> 
     </td> 
    </tr> 
</xsl:template> 

W powyższym XSLT, pod komentarzem okolicy, muszę dopasować i wyświetlić klientów, którzy Adres nie jest istniejący w Adresy/węzeł adresu.

Proszę pomóc znaleźć wyrażenie XPath, które będzie pasować do klientów, którzy NIE są w zestawie węzłów adresów. (Każda alternatywny może również pomóc)

+0

Dobre pytanie (+1). Zobacz moją odpowiedź na wydajne, krótkie i proste rozwiązanie XSLT. :) –

Odpowiedz

7

W Xpath 1.0:

/Message/Customers/Customer[not(@pin=/Message/Addresses/Address/@pin1)] 
+0

Wow, to działa dobrze. Dziękuję bardzo. – SaravananArumugam

+0

@Saravanandss: Powodzenia! –

+0

+1. Jest to podstawowa wiedza XPath - niestety OP jest szczęśliwy, że "działa" i prawdopodobnie nie zagłębiłby się dalej, by zrozumieć, co się właściwie dzieje ... :( –

4

Alternatywą dla dobrej odpowiedzi przez @Alejandro, które upvoted, jest po transformacji, który wykorzystuje klucze i będzie bardziej efektywne, jeżeli liczba obecnych klientów jest duży:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:key name="kexistingByPin" 
     match="Address" use="@pin1"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select= 
    "*/*/Customer[not(key('kexistingByPin', @pin))]"/> 
</xsl:template> 
</xsl:stylesheet> 

kiedy ta transformacja jest stosowane na dostarczonym dokumencie XML:

<Message> 
    <Customers> 
     <Customer pin="06067">1</Customer> 
     <Customer pin="06068">2</Customer> 
     <Customer pin="06069">3</Customer> 
     <Customer pin="06070">4</Customer> 
     <Customer pin="06072">5</Customer> 
    </Customers> 
    <Addresses> 
     <Address pin1="06067">A</Address> 
     <Address pin1="06068">B</Address> 
     <Address pin1="06069">C</Address> 
    </Addresses> 
</Message> 

poszukiwany, poprawna odpowiedź jest produkowany:

<Customer pin="06070">4</Customer> 
<Customer pin="06072">5</Customer>