Subject: Re: [xsl] Find the number of elements that are prior to the series of elements that match a string? From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Tue, 12 Mar 2019 20:20:39 -0000 |
Here is an XSLT 2.0 solution using keys. In its current form it returns the wanted offset (length) as a hexadecimal number. To convert this to a decimal number, have a look at the archives where AFAIR there is such code -- could be even posted by me ... This conversion to decimal can certainly be written elegantly as fold-left() in XSLT/XPath 3 Also, the key is not generated based on the length of the searched string (as in Elliot's solution), because I believe the transformation will be more useful if it can process multiple searches with varying lengths during the life of the transformation. <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:key name="kByteByVal" match="Byte" use="."/> <xsl:param name="pTarget" select="'04000000FF'"/> <xsl:template match="/"> <xsl:variable name="vMatchingHeads" select="key('kByteByVal', substring($pTarget, 1,2))" as="node()*"/> <xsl:variable name="vSolution" select= "$vMatchingHeads[string-join(. | following-sibling::*[not(position() ge string-length($pTarget) idiv 2)], '') eq $pTarget][1]"/> <xsl:value-of select="$vSolution/@hexAddress"/> </xsl:template> </xsl:stylesheet> When this transformation is applied on the following XML document (similar to the originally provided one, but added another 04 to make the case more realistic: <Bytes> <Byte hexAddress="0">4D</Byte> <Byte hexAddress="1">5A</Byte> <Byte hexAddress="2">90</Byte> <Byte hexAddress="3">00</Byte> <Byte hexAddress="4">03</Byte> <Byte hexAddress="5">04</Byte> <Byte hexAddress="6">00</Byte> <Byte hexAddress="7">00</Byte> <Byte hexAddress="8">00</Byte> <Byte hexAddress="9">04</Byte> <Byte hexAddress="A">00</Byte> <Byte hexAddress="B">00</Byte> <Byte hexAddress="C">00</Byte> <Byte hexAddress="D">FF</Byte> <Byte hexAddress="E">FF</Byte> </Bytes> the wanted result is produced: 9 Cheers, Dimitre On Tue, Mar 12, 2019 at 11:01 AM Michael Kay mike@xxxxxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > > My instinct is to use index-of() to get the positions of the elements that match the first required byte, and then for each of these positions, form the string of N bytes starting at this position and do a string comparison to test whether there is a match at this position. > > let $candidates := index-of(/Bytes/Byte, substring($req, 1, 2)) > return $candidates[string-join(subsequence(/Bytes/Byte, ., $len), '') eq $req][1] - 1 > > Michael Kay > Saxoniica > > > > > On 12 Mar 2019, at 17:35, Costello, Roger L. costello@xxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > > > Hi Folks, > > > > I have an XML document containing a long list of Byte elements, e.g., > > > > <Bytes> > > <Byte hexAddress="0">4D</Byte> > > <Byte hexAddress="1">5A</Byte> > > <Byte hexAddress="2">90</Byte> > > <Byte hexAddress="3">00</Byte> > > <Byte hexAddress="4">03</Byte> > > <Byte hexAddress="5">00</Byte> > > <Byte hexAddress="6">00</Byte> > > <Byte hexAddress="7">00</Byte> > > <Byte hexAddress="8">04</Byte> > > <Byte hexAddress="9">00</Byte> > > <Byte hexAddress="A">00</Byte> > > <Byte hexAddress="B">00</Byte> > > <Byte hexAddress="C">FF</Byte> > > <Byte hexAddress="D">FF</Byte> > > ... > > </Bytes> > > > > I have a string of hex values, e.g., > > > > 04000000FF > > > > You can see that the string is contained within this series of Byte elements: > > > > <Byte hexAddress="8">04</Byte> > > <Byte hexAddress="9">00</Byte> > > <Byte hexAddress="A">00</Byte> > > <Byte hexAddress="B">00</Byte> > > <Byte hexAddress="C">FF</Byte> > > > > I want to find the number of <Byte> elements that occur prior to the series of Byte elements. > > > > I figured one approach is to convert all the Byte text node values into a string and then perform string manipulations: > > > > string-length(substring-before(string-join(/Bytes/Byte/text(), ''), '04000000FF')) idiv 2 > > > > Note: I divided by two because each Byte has 2 digits. > > > > That seems to work, but I suspect it is horribly inefficient because it creates a string containing all the Byte text node values and there may be tens or hundreds of thousands of Byte elements. > > > > What is an efficient way to solve this problem? > > > > /Roger > > > > > > > > > -- Cheers, Dimitre Novatchev --------------------------------------- Truly great madness cannot be achieved without significant intelligence. --------------------------------------- To invent, you need a good imagination and a pile of junk ------------------------------------- Never fight an inanimate object ------------------------------------- To avoid situations in which you might make mistakes may be the biggest mistake of all ------------------------------------ Quality means doing it right when no one is looking. ------------------------------------- You've achieved success in your field when you don't know whether what you're doing is work or play ------------------------------------- To achieve the impossible dream, try going to sleep. ------------------------------------- Facts do not cease to exist because they are ignored. ------------------------------------- Typing monkeys will write all Shakespeare's works in 200yrs.Will they write all patents, too? :) ------------------------------------- Sanity is madness put to good use. ------------------------------------- I finally figured out the only reason to be alive is to enjoy it.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Find the number of elemen, Michael Kay mike@xxx | Thread | Re: [xsl] Find the number of elemen, Michael Kay mike@xxx |
Re: [xsl] Find the number of elemen, Michael Kay mike@xxx | Date | Re: [xsl] Find the number of elemen, Michael Kay mike@xxx |
Month |