xsl-list
[Top] [All Lists]

Re: [xsl] An XPath expression that avoids writing special case code?

2021-06-17 09:16:20
This is a case for pipelines. First run a transformation that turns your 
document into something that better represents thet semantics, like

<airports>
  <airport>LHR</airport>
  <airport>LAX</airport>
</airports>

and then do your actual query against this document.

This gives you separation of concerns, and the first transformation in the 
pipeline is reusable code, you can use it regardless what query the second 
stage needs to perform.

When you're dealing with data that originates from spreadsheets, where you 
often have to deal with complexities like rowspans and columnspans, this 
pipeline approach is the only way to preserve your sanity.

Michael Kay
Saxonica

On 17 Jun 2021, at 15:06, Roger L Costello costello(_at_)mitre(_dot_)org 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Hi Folks,

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?

/Roger


--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--


<Prev in Thread] Current Thread [Next in Thread>