Comparing node sets

Discussion in 'XML' started by Doug, Jul 25, 2003.

  1. Doug

    Doug Guest

    I need to compare two "address" structures within a document, and
    perform some action if they are not equal.

    The XML document is a purchase order, with an address at both the
    header and line item level:

    <Order>
    <Header>
    ... other header level stuff ...
    <Address>
    <AddressLine>address 1</AddressLine>
    <AddressLine>address 2</AddressLine>
    <CityName>city</CityName>
    <PostalCode>post code</PostalCode>
    <PostalCountry>country</PostalCountry>
    </Address>
    </Header>
    <Body>
    <LineItem>
    ... other line item stuff ...
    <Address>
    <AddressLine>address 1</AddressLine>
    <AddressLine>address 2</AddressLine>
    <CityName>city</CityName>
    <PostalCode>post code</PostalCode>
    <PostalCountry>country</PostalCountry>
    </Address>
    </LineItem>
    <LineItem>
    ... other line item stuff ...
    <Address>
    <AddressLine>somewhere different</AddressLine>
    <CityName>other city</CityName>
    <PostalCode>other post code</PostalCode>
    <PostalCountry>country</PostalCountry>
    </Address>
    </LineItem>
    </Body>
    </Order>


    For line items where the address is the same as the header level
    address I need take no action. For addresses which differ I need to
    populate an output attribute with a value. Therefore, ideally I'm
    looking for an expression that I can use in the test clause of an "if"
    element.

    How can I compare the two address structures? I want "true" to mean
    both structures are completely identical in element name, order and
    value. In the above example the first line item's address is identical
    to the header level, the second is different.

    Is it possible to do this with XSLT? Can the XML be accessed in a
    string format (like the .xml method of a node in DOM), so that I can
    compare the resulting strings?

    Thanks in advance for any help.

    Doug
     
    Doug, Jul 25, 2003
    #1
    1. Advertising

  2. Doug

    Marrow Guest

    Hi Doug,

    You could try copying the two node-sets into two RTFs (result tree
    fragments) and then comparing the two RTFs, e.g. something along the lines
    of...

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:eek:utput method="text"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="Order">
    <xsl:variable name="setHdr">
    <xsl:copy-of select="Header/Address"/>
    </xsl:variable>
    <xsl:variable name="setAdd1">
    <xsl:copy-of select="Body/LineItem[1]/Address"/>
    </xsl:variable>
    <xsl:variable name="setAdd2">
    <xsl:copy-of select="Body/LineItem[2]/Address"/>
    </xsl:variable>
    <xsl:text>(Header/Address = Body/LineItem[1]/Address) ? </xsl:text>
    <xsl:value-of select="$setHdr = $setAdd1"/>
    <xsl:text>
    </xsl:text>
    <xsl:text>(Header/Address = Body/LineItem[2]/Address) ? </xsl:text>
    <xsl:value-of select="$setHdr = $setAdd2"/>
    </xsl:template>
    </xsl:stylesheet>

    That may be sufficient for what you need.
    The <xsl:strip-space elements="*"/> is required in case you have white-space
    preservation turned on for the input XML - otherwise the additional
    indentation on the deeper addresses will be preserved and cause a result of
    false for both comparisons.
    Although even that may have a pit-fall - if you should have an explicit
    xml:space="preserve" in the XML that preserves the whitespace indentation.
    For example...

    <Order xml:space="preserve">
    <Header>
    ... other header level stuff ...
    <Address>
    <AddressLine>address 1</AddressLine>
    <AddressLine>address 2</AddressLine>
    <CityName>city</CityName>
    <PostalCode>post code</PostalCode>
    <PostalCountry>country</PostalCountry>
    </Address>
    </Header>
    <Body>
    <LineItem>
    ... other line item stuff ...
    <Address>
    <AddressLine>address 1</AddressLine>
    <AddressLine>address 2</AddressLine>
    <CityName>city</CityName>
    <PostalCode>post code</PostalCode>
    <PostalCountry>country</PostalCountry>
    </Address>
    </LineItem>
    <LineItem>
    ... other line item stuff ...
    <Address>
    <AddressLine>somewhere different</AddressLine>
    <CityName>other city</CityName>
    <PostalCode>other post code</PostalCode>
    <PostalCountry>country</PostalCountry>
    </Address>
    </LineItem>
    </Body>
    </Order>

    In that case you'd need to make the stylesheet a little more complex, e.g.

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:eek:utput method="text"/>
    <xsl:template match="Order">
    <xsl:variable name="setHdr">
    <xsl:apply-templates select="Header/Address" mode="rtfcopy"/>
    </xsl:variable>
    <xsl:variable name="setAdd1">
    <xsl:apply-templates select="Body/LineItem[1]/Address" mode="rtfcopy"/>
    </xsl:variable>
    <xsl:variable name="setAdd2">
    <xsl:apply-templates select="Body/LineItem[2]/Address" mode="rtfcopy"/>
    </xsl:variable>
    <xsl:text>(Header/Address = Body/LineItem[1]/Address) ? </xsl:text>
    <xsl:value-of select="$setHdr = $setAdd1"/>
    <xsl:text>
    </xsl:text>
    <xsl:text>(Header/Address = Body/LineItem[2]/Address) ? </xsl:text>
    <xsl:value-of select="$setHdr = $setAdd2"/>
    </xsl:template>

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

    <xsl:template match="@* | comment() | processing-instruction()"
    mode="rtfcopy">
    <xsl:copy/>
    </xsl:template>

    <xsl:template match="text()" mode="rtfcopy">
    <xsl:if test="normalize-space(.)">
    <xsl:copy/>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

    NB. the modes are only there so that the copying templates don't interfere
    with any other templates you might have.

    Hope this helps
    Marrow
    http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
    http://www.topxml.com/Xselerator

    "Doug" <> wrote in message
    news:...
    > I need to compare two "address" structures within a document, and
    > perform some action if they are not equal.
    >
    > The XML document is a purchase order, with an address at both the
    > header and line item level:
    >
    > <Order>
    > <Header>
    > ... other header level stuff ...
    > <Address>
    > <AddressLine>address 1</AddressLine>
    > <AddressLine>address 2</AddressLine>
    > <CityName>city</CityName>
    > <PostalCode>post code</PostalCode>
    > <PostalCountry>country</PostalCountry>
    > </Address>
    > </Header>
    > <Body>
    > <LineItem>
    > ... other line item stuff ...
    > <Address>
    > <AddressLine>address 1</AddressLine>
    > <AddressLine>address 2</AddressLine>
    > <CityName>city</CityName>
    > <PostalCode>post code</PostalCode>
    > <PostalCountry>country</PostalCountry>
    > </Address>
    > </LineItem>
    > <LineItem>
    > ... other line item stuff ...
    > <Address>
    > <AddressLine>somewhere different</AddressLine>
    > <CityName>other city</CityName>
    > <PostalCode>other post code</PostalCode>
    > <PostalCountry>country</PostalCountry>
    > </Address>
    > </LineItem>
    > </Body>
    > </Order>
    >
    >
    > For line items where the address is the same as the header level
    > address I need take no action. For addresses which differ I need to
    > populate an output attribute with a value. Therefore, ideally I'm
    > looking for an expression that I can use in the test clause of an "if"
    > element.
    >
    > How can I compare the two address structures? I want "true" to mean
    > both structures are completely identical in element name, order and
    > value. In the above example the first line item's address is identical
    > to the header level, the second is different.
    >
    > Is it possible to do this with XSLT? Can the XML be accessed in a
    > string format (like the .xml method of a node in DOM), so that I can
    > compare the resulting strings?
    >
    > Thanks in advance for any help.
    >
    > Doug
     
    Marrow, Jul 25, 2003
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    1,468
  2. Andy Fish

    xpath: comparing two node sets

    Andy Fish, Mar 9, 2005, in forum: XML
    Replies:
    3
    Views:
    2,756
    Andy Fish
    Mar 10, 2005
  3. John Salerno

    comparing values in two sets

    John Salerno, May 14, 2006, in forum: Python
    Replies:
    11
    Views:
    560
    Gerard Flanagan
    May 15, 2006
  4. Tjerk Wolterink
    Replies:
    2
    Views:
    1,438
    Dimitre Novatchev
    Aug 24, 2006
  5. Replies:
    3
    Views:
    260
    Asun Friere
    Jul 10, 2007
Loading...

Share This Page