[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: An XPath expression that avoids writing special c

Subject: Re: An XPath expression that avoids writing special casecode?
From: "Roger L Costello costello@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 18 Jun 2021 16:23:43 -0000
Re:  An XPath expression that avoids writing special  c
Wendell wrote:

> In the first case, the step 'string(Data)', in the absence of a Data node,
> will return '', since string(()) (a string value of nothing) is an empty
string,
> i.e. a sequence of one member, ('').

> In the second case, the failure of the path to reach any node at Data
results
> in the comparison () eq '' which should produce a runtime error, since 'eq'
> requires two singleton operands.

Ah!

Fantastic explanation!

Thank you Wendell.

/Roger

From: Wendell Piez wapiez@xxxxxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Friday, June 18, 2021 12:02 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [EXT] Re:  An XPath expression that avoids writing special
casecode?

Roger,

You ask

> Question: Below are two XPath expressions. The first is the one that Mukul
recommended and it returns the desired row. The second is the one that I
created and it fails. The only difference between the two XPath expressions is
string(Data) versus Data. Why does the former work whereas the later fails?

> /Document/Row[Cell[1]/Data eq 'aviation'][Cell[2]/string(Data) eq '']
> /Document/Row[Cell[1]/Data eq 'aviation'][Cell[2]/Data eq '']

In the first case, the step 'string(Data)', in the absence of a Data node,
will return '', since string(()) (a string value of nothing) is an
emptyB string, i.e. a sequence of one member, ('').

In the second case, the failure of the path to reach any node at Data results
in the comparison () eq '' which should produce a runtime error, since 'eq'
requires two singleton operands.

It is useful to keep in mind the distinction between a test for the existence
of a node, and a test for a node's value. The operators such as '=' have the
nice feature of letting us collapse these things since itB permits
many-to-many or many-to-none comparisons. The 'eq' operator has the nice
feature of not letting us collapse these things.

Cheers,
Wendell





On Fri, Jun 18, 2021 at 9:31 AM Roger L Costello mailto:costello@xxxxxxxxx
<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
Hi Mukul,

I tried your suggestion. For this XML document:

<Document>
B  B  <Row>
B  B  B  B  <Cell>
B  B  B  B  B  B  <Data>aviation</Data>
B  B  B  B  </Cell>
B  B  B  B  <Cell/>
B  B  </Row>
</Document>

I evaluated the following XPath expression in Oxygen XML:

/Document/Row[Cell[1]/Data eq 'aviation'][Cell[2]/string(Data) eq '']

Oxygen XML returned the desired row:

B  B  <Row>
B  B  B  B  <Cell>
B  B  B  B  B  B  <Data>aviation</Data>
B  B  B  B  </Cell>
B  B  B  B  <Cell/>
B  B  </Row>

Fantastic!

Question: Below are two XPath expressions. The first is the one that Mukul
recommended and it returns the desired row. The second is the one that I
created and it fails. The only difference between the two XPath expressions is
string(Data) versus Data. Why does the former work whereas the later fails?

/Document/Row[Cell[1]/Data eq 'aviation'][Cell[2]/string(Data) eq '']
/Document/Row[Cell[1]/Data eq 'aviation'][Cell[2]/Data eq '']

/Roger


From: Mukul Gandhi mailto:mukulg@xxxxxxxxxxxxxxxxx
<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Friday, June 18, 2021 3:28 AM
To: mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [EXT] Re:  An XPath expression that avoids writing special
casecode?

On Thu, Jun 17, 2021 at 7:36 PM Roger L Costello
mailto:mailto:costello@xxxxxxxxx
<mailto:mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
B 
My XML document contains a bunch of <Row> elements, like so:

<Document>
B  B  ...
B  B  <Row>
B  B  B  B  <Cell>
B  B  B  B  B  B  <Data>airport</Data>
B  B  B  B  </Cell>
B  B  B  B  <Cell>
B  B  B  B  B  B  <Data>airports</Data>
B  B  B  B  </Cell>
B  B  </Row>
B  B  ...
</Document>

I want to fetch the Row whose Cell[1]/Data is 'airport' and whose Cell[2]/Data
is 'airports'. So I created this XPath expression:

/Document/Row[Cell[1]/Data eq 'airport'][Cell[2]/Data eq 'airports']

I do this kind of fetching operation often, so I created a function to fetch
the desired Row:

<xsl:function name="f:getRow">
B  B  <xsl:param name="element"/>
B  B  <xsl:param name="parent"/>
B  B  <xsl:sequence select="$document/Row[Cell[1]/Data eq
$element][Cell[2]/Data eq $parent]" />
</xsl:function>

I call the function this way:

<xsl:sequence select="f:getRow('airport', 'airports')" />

Sometimes there is an element that doesn't have a parent. That is, sometimes
I'd like to fetch a Row in which Cell[2] is empty, like this:

B  B  <Row>
B  B  B  B  <Cell>
B  B  B  B  B  B  <Data>aviation</Data>
B  B  B  B  </Cell>
B  B  B  B  <Cell/>
B  B  </Row>

Then this call to f:getRow fails:

<xsl:sequence select="f:getRow('aviation', '')" />B  B  B  B  <!-- Those are
two apostrophes within the parentheses -->

Clearly I need to modify f:getRow. I could add special case code to test
$parent to see if it is empty (the '' string) and do one thing, and if it's
not empty do another thing. But I wonder if there is a more elegant solution
that doesn't involve special case code? Is there a way to modify the XPath
expression in f:getRow such that it fetches the correct Row regardless of
whether $parent is empty or not?

Testing with XSLT 2.0. Below is an example, for the solution you may be
looking for,

XML input document,

<Document>
B  B  <Row>
B  B  B  B <Cell>
B  B  B  B  B  <Data>airport</Data>
B  B  B  B </Cell>
B  B  B  B <Cell>
B  B  B  B  B  <Data>airports</Data>
B  B  B  B </Cell>
B  B  </Row>
B  B  <Row>
B  B  B  B <Cell>
B  B  B  B  B  <Data>airport</Data>
B  B  B  B </Cell>
B  B  B  B <Cell>
B  B  B  B  B  <Data>ABC</Data>
B  B  B  B </Cell>
B  B  </Row>
B  B  <Row>
B  B  B  <Cell>
B  B  B  B  B <Data>aviation</Data>
B  B  B  </Cell>
B  B  B  <Cell/>
B  B  </Row>
</Document>B 

XSLT stylesheet,

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
B  B  B  B  B  B  B  B  B  B  B  B  B xmlns:f="http://test_fn"
B  B  B  B  B  B  B  B  B  B  B  B  B exclude-result-prefixes="f"
B  B  B  B  B  B  B  B  B  B  B  B  B version="2.0">

B  B <xsl:output method="xml" indent="yes"/>
B  B 
B  B <xsl:variable name="document" select="/Document"/>

B  B <xsl:template match="/">
B  B  B  <result>
B  B  B  B  B <xsl:copy-of select="f:getRow('airport', 'airports')"/>
B  B  B  B  B <xsl:copy-of select="f:getRow('aviation', '')"/>
B  B  B  </result>
B  B </xsl:template>
B  B 
B  B <xsl:function name="f:getRow">
B  B  B <xsl:param name="element"/>
B  B  B <xsl:param name="parent"/>
B  B  B <xsl:sequence select="$document/Row[Cell[1]/Data eq
$element][Cell[2]/string(Data) eq $parent]" />
B  B </xsl:function>

</xsl:stylesheet>

The output of above XSLT transformation is following,

<?xml version="1.0" encoding="UTF-8"?>
<result>
B  B <Row>
B  B  B  B <Cell>
B  B  B  B  B  <Data>airport</Data>
B  B  B  B </Cell>
B  B  B  B <Cell>
B  B  B  B  B  <Data>airports</Data>
B  B  B  B </Cell>
B  B  </Row>
B  B <Row>
B  B  B  <Cell>
B  B  B  B  B <Data>aviation</Data>
B  B  B  </Cell>
B  B  B  <Cell/>
B  B  </Row>
</result>



--
Regards,
Mukul Gandhi
http://www.mulberrytech.com/xsl/xsl-list
http://lists.mulberrytech.com/unsub/xsl-list/673357 ()




--
...Wendell Piez... ...wendell -at- nist -dot- gov...
...wendellpiez.com... ...pellucidliterature.org... ...pausepress.org...
...http://github.com/wendellpiez... ...gitlab.coko.foundation/wendell...
http://www.mulberrytech.com/xsl/xsl-list
http://lists.mulberrytech.com/unsub/xsl-list/673357 ()

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.