The data can be parsed by two regex steps.
The first tags the lines.
The second converts each line into a [t:]tide-level element.
Here is part of those two steps:
<p:regex select="h:pre" pattern=".+" matches="line"/> <p:regex select="line" pattern="^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)"> <p:template> <xsl:param name="group-1"/> <xsl:param name="group-2"/> <xsl:param name="group-3"/> <xsl:param name="group-4"/> <xsl:variable name="month" select="substring-before($group-1,'/')"/> <xsl:variable name="day" select="substring-before(substring-after($group-1,'/'),'/')"/> <xsl:variable name="year" select="substring-after(substring-after($group-1,'/'),'/')"/> <t:tide-level date="{$year}-{$month}-{$day}" level="{$group-4}"> <xsl:choose> <xsl:when test="$group-3='EST'"> <xsl:attribute name="time"><xsl:value-of select="$group-2"/>-5:00</xsl:attribute> </xsl:when> <xsl:when test="$group-3='EDT'"> <xsl:attribute name="time"><xsl:value-of select="$group-2"/>-4:00</xsl:attribute> </xsl:when> ... </t:tide-level> </p:template> </p:regex>