Domanda

Ho un po 'di XML, ad esempio per scopi che sembrano così:

<root>
    <field1>test</field1>
    <f2>t2</f2>
    <f2>t3</f2>
</root>

Voglio trasformarlo con XSLT, ma voglio sopprimere il secondo elemento f2 nell'output - come posso controllare all'interno del mio modello per vedere se l'elemento f2 esiste già nell'output quando il secondo elemento f2 nell'origine è processato? La mia XSLT è simile a questa al momento:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no" omit-xml-declaration="yes" standalone="no" />
  <xsl:template match="/">
    <xsl:for-each select="./root">
      <output>
        <xsl:apply-templates />        
      </output>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="*" >
      <xsl:element name="{name(.)}">
        <xsl:value-of select="." />
      </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Devo fare una sorta di controllo intorno all'elemento xsl: nel modello, penso, ma non sono sicuro di come interrogare il documento di output per vedere se l'elemento è già presente.

Modifica: ho dimenticato i pre tag, il codice dovrebbe essere visibile ora!

È stato utile?

Soluzione

Dipende da quanto sistema vuoi essere.

vale a dire. Ti preoccupi solo di elementi che sono figli dello stesso genitore o di tutti gli elementi allo stesso livello ("cugini" se preferisci) o elementi in qualsiasi parte del documento ...

Nella prima situazione è possibile controllare l'asse del fratello precedente per vedere se esistono altri elementi con lo stesso nome.

<xsl:if test="count(preceding-sibling::node()[name()=name(current())])=0">
  ... do stuff in here.
</xsl:if>

Altri suggerimenti

Per controllare (e avvisarti di un duplicato), potresti trovare un esempio qui

Qualcosa sulla falsariga di:

<xsl:for-each-group select="collection(...)//@id" group-by=".">
  <xsl:if test="count(current-group()) ne 1">
    <xsl:message>Id value <xsl:value-of select="current-grouping-key()"/> is 
       duplicated in files
       <xsl:value-of select="current-group()/document-uri(/)" separator=" and
    "/></xsl:message>
  </xsl:if>
 </xsl:for-each-group>

Da modificare per selezionare tutti i nodi all'interno dell'elemento 'root'.

Per rimuovere le righe duplicate, hai un altro esempio qui

Sarebbe simile a:

<xsl:stylesheet>
  <xsl:key name="xyz" match="record[x/y/z]" use="x/y/z" />
  <xsl:variable name="noxyzdups" select="/path/to/record[generate-id(.) = generate-id(key('xyz', x/y/z))]" />
...
  <xsl:template ... >
    <xsl:copy-of "exslt:node-set($noxyzdups)" />
  </xsl:template>
</xsl:stylesheet>

x / y / z è l'espressione xpath che vuoi rendere unica. Può essere concat (x, '-', @ y, '-', z) o qualunque cosa tu voglia.

Ora non sono sicuro che quei due esempi possano essere facilmente adattati al tuo caso, ma volevo solo sottolineare quelle due fonti, nel caso in cui ciò aiuti.

Non è possibile interrogare l'output della tua trasformazione. Inoltre, non è possibile tenere traccia dello stato corrente della trasformazione (ovvero tenere traccia di quali nodi sono stati emessi in una variabile). Fondamentalmente, non è così che funziona XSLT. Uno dei costi di un ambiente di programmazione privo di effetti collaterali è che non puoi fare cose che hanno effetti collaterali. Oh bene.

Nel tuo caso, un modo per raggiungere questo obiettivo sarebbe quello di costruire una variabile che contenesse un elenco di tutti gli elementi di origine che potrebbero essere trasformati nell'elemento di output che si desidera emettere una sola volta. Quindi controlla ogni nodo che stai trasformando in questo elenco. Se non è nell'elenco, emettilo. Se è il primo elemento nell'elenco, emettilo. Altrimenti, no.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top