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 |