Roberto
Roberto

Reputation: 135

Create a table from a tei document xml with xslt

I have an XML like that:

<body>
      <div type="capitolo">
          <div n="7" type="pag">
            <head>Prologo</head>
            <p>
               Le tenebre stavano avanzando.
            </p>
            <p>
                <said rend="pre(«) post(»)">Meglio Rientrare.</said> <name type="gar">Gared</name> osservò i boschi attorno a 
                loro farsi più oscuri. <said rend="pre(«) post(»)">I bruti sono morti.</said>
            </p>
            <p>
               <said rend="pre(«) post(»)">Da quando hai paura dei morti?</said> C'era l'accenno di un sorriso sui lineamenti di 
                ser <name type="way">Waymar Royce</name>.
            </p>
            <p>
               <name type="gar">Gared</name> non raccolse. Era un uomo in età, oltre i cinquanta, e di e di nobili ne aveva visti andare 
                e venire molti. <said rend="pre(«) post(»)">Ciò che è morto resta morto</said>         disse <said rend="pre(«) post(»)">e noi non 
                dovremmo averci niente a che fare.</said>
            </p>
            <p>
               <said rend="pre(«) post(»)">Che prova abbiamo che sono davvero morti?</said> chiese <name type="way">Royce</name> a bassa voce.
            </p>
            <p>
               <said rend="pre(«) post(»)"><name type="will">Will</name> li ha visti. Come prova, a me basta.</said>
            </p>
            <p>
               <name type="will">Will</name> sapeva che prima o poi l'avrebbero trascinato nella discussione. Aveva sperato che accadesse dopo, 
                piuttosto che prima. <said rend="pre(«) post(»)">Mia madre diceva che i morti non parlano</said> s'intromise.
            </p>
            <p>
                <said rend="pre(«) post(»)">Davvero, <name type="will">Will</name>?</said> rispose <name type="way">Royce</name>. 
                <said rend="pre(«) post(»)">E' la stessa cosa che mi diceva la mia balia. Mai credere a quello che si sente vicino alle tette di una donna. 
                C'è sempre da imparare, perfino dai morti.</said>
            </p>
            <p>
                La foresta piena d'ombre rimandò echi della voce di ser <name type="way">Waymar</name>. Troppi echi, troppo forti e definiti.</p>
            <p>
                <said rend="pre(«) post(»)">Ci aspetta una lunga cavalcata</said> insistè <name type="gar">Gared</name> 
                <said rend="pre(«) post(»)"> Otto giorni, forse nove. E sta calando la notte.</said>
            </p></div></body>

I have to create an html table with XSLT where

Column 1: for each "name" tag that I have considering the different @types the value of the tag name (if the type is coming a new time don't write another time that name)

Column 2: for the type selected in that row all the @n that we can find that @type

Can you please help me?

Upvotes: 1

Views: 248

Answers (1)

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25054

Welcome to Stack Overflow!

Some advice. You will normally get better answers to questions on Stack Overflow if you show the code you currently are trying to run, which is not working right. (If you haven't written any code, most readers of Stack Overflow will assume you just want someone else to write your code for you, and they will ignore your question or rebuke you for being lazy. This means that if you have no code, because you have no idea how to proceed, you need to ask your question very carefully.) The Stack Overflow FAQ on asking good quesitons is worth reading and gives good advice. The essay "How to ask questions the smart way" by Eric Raymond and Rick Moen is also helpful.

First, you probably want to be using the key attribute, not the type attribute, to distinguish the individuals named by the name element.

Then, if you are not sure how to approach your XSLT problem, try breaking it down into smaller problems.

  • First try a stylesheet that produces an HTML table with the text "Watch this space".

    Your XSLT will have one template somewhere that emits the HTML elements needed for a table containing one row.

  • Then try to make a table with one row for each name element in the input. (This is not what you want, yet, because it will have many entries for names that occur many times, but it's closer than "Watch this space", so it's progress.)

    Your XSLT will have one template somewhere (perhaps in the template for body) that emits the HTML table element, and one template for name that emits one table row for that occurrence of name.

  • Then try to think of a way to make each distinct name, or rather each distinct key (or type) attribute, appear only once in the table. In XSLT 2.0, the function distinct-values() is useful in this connection; in XSLT 1.0, the usual approach is to make a name element produce a table row only if it is the first element with its key value. You can use an XPath expression in the match pattern of the appropriate template, or in the test of an xsl:choose/xsl:when element, to test whether a given element is the first of its kind.

    The naive approach to checking whether a given name element is the first or not the first with its key value will sometimes be slow. The usual approach to speeding things up is to use the XSLT key function and a technique referred to a Muenchian Grouping (search for it on the Web; you will find plenty of hits). Muenchian Grouping can be hard to understand if you are new to XSLT, so I would advise you not to bother with it, if the naive approach is fast enough for your current needs -- that is, if you aren't spending a lot of time wishing the XSLT would run faster.

    Depending on how you do it, your stylesheet will now have either a single template for name with an xsl:choose in it to do one thing if it's the first occurrence of the key and another if it's not, or it will have one template for the first-occurrence case and one template for the not-first-occurrence case.

  • Finally, make the stylesheet produce a full list of places where a given name is used. The easy way to do this will be to use the select attribute on xsl:apply-templates within the template for the first occurrence of each name key.

If you are new to XSLT, you may have trouble with any one of these steps. Try it, do the best you can, and ask on Stack Overflow, showing code that illustrates how you are trying to solve the problem. Good luck.

Upvotes: 1

Related Questions