ntg-context - mailing list for ConTeXt users
 help / color / mirror / Atom feed
From: Hans Hagen <pragma@wxs.nl>
To: ntg-context@ntg.nl
Subject: Re: index(register) from an XML source
Date: Sat, 14 Jan 2017 13:53:52 +0100	[thread overview]
Message-ID: <f2ca9eda-9c9e-27c9-5241-87f491900458@wxs.nl> (raw)
In-Reply-To: <1484327413.11845.3.camel@fastwebnet.it>

On 1/13/2017 6:10 PM, MF wrote:
> Hello list,
> please see this:
> ----------------------------------------
> \startbuffer[test]
> <text>
>   <div>
>     <p>In this page there is a <name idref="id1">cat</name>,
>       a <name idref="id2">dog</name>
>      and a <name idref="id3">horse</name>.</p>
>   </div>
>   <div>
>     <p>In this page there's only a <name idref="id2">fox
> terrier</name>.</p>
>   </div>
>   <div>
>     <p>In this page you find a <name idref="id1">persian cat</name>
>      and a <name idref="id3">horse</name>.</p>
>   </div>
>   <index>
>     <entry id="id1" data-sort="cat">Cat</entry>
>     <entry id="id2" data-sort="dog">Dog</entry>
>     <entry id="id3" data-sort="horse">Horse</entry>
>   </index>
> </text>
> \stopbuffer
>
> \defineregister[Animal][Animals]
>
> \startxmlsetups xml:mysetup
>   \xmlsetsetup{#1}{text|div|p|name|i|index|entry}{xml:*}
> \stopxmlsetups
>
> \xmlregistersetup{xml:mysetup}
>
> \startxmlsetups xml:text
>   \xmlflush{#1}
> \stopxmlsetups
>
> \startxmlsetups xml:div
>   \xmlflush{#1}\page
> \stopxmlsetups
>
> \startxmlsetups xml:p
>   \xmlflush{#1}\par
> \stopxmlsetups
>
> \startxmlsetups xml:name
>
> \Animal[\xmlfunction{#1}{sortKeyOfAnimal}]{\xmlfunction{#1}{indexEntryF
> orAnimal}}{\bf\xmlflush{#1}}
> \stopxmlsetups
>
> \startxmlsetups xml:i
>   \dontleavehmode{\em\xmlflush{#1}}
> \stopxmlsetups
>
> \startxmlsetups xml:index
>   \placeregister[Animal]
> \stopxmlsetups
>
> \startxmlsetups xml:entry
>   \xmlflush{#1}
> \stopxmlsetups
>
> \startluacode
> userdata = userdata or {}
> userdata.animals = {}
>
> function userdata.findAnimal(t)
>   local idref = xml.attribute(t, "", "idref")
>   local animal = userdata.animals[idref]
>   if not animal then
>     local entry = xml.first(t, "ancestor::text//index/entry[@id = '" ..
> idref .. "']")
>     local sortkey = xml.attribute(entry, "", "data-sort")
>     animal = {}
>     if sortkey and entry then
>       animal.id = idref
>       animal.sortkey = sortkey
>       animal.entry = entry
>       userdata.animals[idref] = animal
>     end
>   end
>   return animal
> end
>
> function xml.functions.sortKeyOfAnimal(t)
>   local animal = userdata.findAnimal(t)
>   if animal.sortkey then
>     context(animal.sortkey)
>   else
>     context("zzz")
>   end
> end
>
> function xml.functions.indexEntryForAnimal(t)
>   local animal = userdata.findAnimal(t)
>   if animal.entry then
>     lxml.flush(animal.entry)
>   end
> end
> \stopluacode
>
> \starttext
>   \xmlprocessbuffer{main}{test}{}
> \stoptext
> ----------------------------------------
>
> It's a simplified version of the documents I'm working on:
> - it's XML
> - the index entries are already defined
> - the entries of the index have an "id" attribute and they are
> referred in the main text with an "idref" attribute
> - \Animal[sortkey]{entry} is used to index the terms in the text
> - "sortkey" and "entry" are calculated by the Lua code, that reads the
> idref and finds the right entry inside the <index> element (it also
> caches the entries)
>
> Context has no problems with that code, but the index I get (page 4) is
> something like this:
>
> c
> Cat 1
> Cat 3
>
> d
> Dog 1
> Dog 2
>
> h
> Horse 1
> Horse 3
>
> What I'd expect is instead:
>
> c
> Cat 1,3
>
> d
> Dog 1,2
>
> h
> Horse 1,3
>
> Could you explain me why everytime I get a distinct entry in the index,
> even when the sort key and the entry are the same? (or I only think
> they are, but they are not really)

Take a look at the tuc file ...

     ["list"]={
      { "\\xmlfunction {main::6}{indexEntryForAnimal}", "dog" },
     },

     ["list"]={
      { "\\xmlfunction {main::10}{indexEntryForAnimal}", "dog" },
     },

so although the key is the same the entry isn't and we can't know which 
one to choose so we consider them variants (one can for instance have 
bold and slanted keys at the same time)

you can wrap the entry in \expanded or nicer is:

\setupregister[expansion=yes]

but if your entries contain markup you might like this more:

\startbuffer[test]
<text>
   <div>
     <p>In this page there is a <name idref="id1">cat</name>,
       a <name idref="id2">dog</name> and a <name 
idref="id3">horse</name>.</p>
   </div>
   <div>
     <p>In this page there's only a <name idref="id2">fox 
terrier</name>.</p>
   </div>
   <div>
     <p>In this page you find a <name idref="id1">persian cat</name>
      and a <name idref="id3">horse</name>.</p>
   </div>
   <index>
     <entry id="id1" data-sort="cat">Cat</entry>
     <entry id="id2" data-sort="dog"><bf>Dog</bf></entry>
     <entry id="id3" data-sort="horse">Horse</entry>
   </index>
</text>
\stopbuffer

\defineregister[Animal][Animals]

\startxmlsetups xml:mysetup
     \xmlsetsetup{#1}{*}{xml:*}
\stopxmlsetups

\xmlregistersetup{xml:mysetup}

\startxmlsetups xml:text
     \xmlfunction{#1}{collectIndex}
     \xmlflush{#1}
\stopxmlsetups

\startxmlsetups xml:bf
     \dontleavehmode
     {\xmlflush{#1}}
\stopxmlsetups

\startxmlsetups xml:div
     \xmlflush{#1}
     \page
\stopxmlsetups

\startxmlsetups xml:p
     \ignorespaces
     \xmlflush{#1}
     \removeunwantedspaces
     \par
\stopxmlsetups

\startxmlsetups xml:name
     \dontleavehmode
     \xmlfunction{#1}{indexEntry}
     {\bf\xmlflush{#1}}
\stopxmlsetups

\startxmlsetups xml:i
     \dontleavehmode
     {\em\xmlflush{#1}}
\stopxmlsetups

\startxmlsetups xml:index
     \placeregister[Animal]
\stopxmlsetups

\startxmlsetups xml:entry
     \xmlflush{#1}
\stopxmlsetups

\startluacode

local animals = { }

function xml.functions.collectIndex(e)
     for entry in xml.collected(e,"/index/entry") do
         local key = entry.at["data-sort"]
         local id  = entry.at["id"]
         if key and id then
             animals[id] = {
                 key   = key,
                 entry = entry,
             }
         end
     end
end

function xml.functions.indexEntry(e)
     local animal = animals[e.at.idref]
     if animal then
         context.Animal (
             { animal.key },
             "\\xmlflush{main::" .. animal.entry.ix .. "}"
         )
     end
end

\stopluacode

\starttext
     \xmlprocessbuffer{main}{test}{}
\stoptext

These #1 are pointers to nodes, so this way (via ix) you access the 
entry itself. Also watch how we collect all entries at the start.

Hans

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

  reply	other threads:[~2017-01-14 12:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-13 17:10 MF
2017-01-14 12:53 ` Hans Hagen [this message]
2017-01-14 14:52   ` MF
2017-01-14 16:34     ` Alan Braslau
2017-01-14 19:40     ` Hans Hagen
2017-01-14 23:07       ` MF

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f2ca9eda-9c9e-27c9-5241-87f491900458@wxs.nl \
    --to=pragma@wxs.nl \
    --cc=ntg-context@ntg.nl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).