|
Subject: Re: [xsl] An XPath expression that avoids writing special casecode? From: "Wendell Piez wapiez@xxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Fri, 18 Jun 2021 16:02:12 -0000 |
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
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.
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
it 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 costello@xxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
> Hi Mukul,
>
> I tried your suggestion. For this XML document:
>
> <Document>
> <Row>
> <Cell>
> <Data>aviation</Data>
> </Cell>
> <Cell/>
> </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:
>
> <Row>
> <Cell>
> <Data>aviation</Data>
> </Cell>
> <Cell/>
> </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 mukulg@xxxxxxxxxxxxxxxxx <
> xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
> Sent: Friday, June 18, 2021 3:28 AM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [EXT] Re: [xsl] An XPath expression that avoids writing special
> casecode?
>
> On Thu, Jun 17, 2021 at 7:36 PM Roger L Costello mailto:costello@xxxxxxxxx
> <mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> My XML document contains a bunch of <Row> elements, like so:
>
> <Document>
> ...
> <Row>
> <Cell>
> <Data>airport</Data>
> </Cell>
> <Cell>
> <Data>airports</Data>
> </Cell>
> </Row>
> ...
> </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">
> <xsl:param name="element"/>
> <xsl:param name="parent"/>
> <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:
>
> <Row>
> <Cell>
> <Data>aviation</Data>
> </Cell>
> <Cell/>
> </Row>
>
> Then this call to f:getRow fails:
>
> <xsl:sequence select="f:getRow('aviation', '')" /> <!-- 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>
> <Row>
> <Cell>
> <Data>airport</Data>
> </Cell>
> <Cell>
> <Data>airports</Data>
> </Cell>
> </Row>
> <Row>
> <Cell>
> <Data>airport</Data>
> </Cell>
> <Cell>
> <Data>ABC</Data>
> </Cell>
> </Row>
> <Row>
> <Cell>
> <Data>aviation</Data>
> </Cell>
> <Cell/>
> </Row>
> </Document>
>
> XSLT stylesheet,
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> xmlns:f="http://test_fn"
> exclude-result-prefixes="f"
> version="2.0">
>
> <xsl:output method="xml" indent="yes"/>
>
> <xsl:variable name="document" select="/Document"/>
>
> <xsl:template match="/">
> <result>
> <xsl:copy-of select="f:getRow('airport', 'airports')"/>
> <xsl:copy-of select="f:getRow('aviation', '')"/>
> </result>
> </xsl:template>
>
> <xsl:function name="f:getRow">
> <xsl:param name="element"/>
> <xsl:param name="parent"/>
> <xsl:sequence select="$document/Row[Cell[1]/Data eq
> $element][Cell[2]/string(Data) eq $parent]" />
> </xsl:function>
>
> </xsl:stylesheet>
>
> The output of above XSLT transformation is following,
>
> <?xml version="1.0" encoding="UTF-8"?>
> <result>
> <Row>
> <Cell>
> <Data>airport</Data>
> </Cell>
> <Cell>
> <Data>airports</Data>
> </Cell>
> </Row>
> <Row>
> <Cell>
> <Data>aviation</Data>
> </Cell>
> <Cell/>
> </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...
...github.com/wendellpiez... ...gitlab.coko.foundation/wendell...
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [xsl] An XPath expression that , Roger L Costello cos | Thread | Re: [xsl] An XPath expression that , Roger L Costello cos |
| Re: [xsl] An XPath expression that , Roger L Costello cos | Date | Re: [xsl] An XPath expression that , Roger L Costello cos |
| Month |