Pergunta

Eu tenho alguns XML, para fins de exemplo, parece que isso:

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

Eu quero transformá-lo com XSLT, mas eu quero suprimir o segundo elemento F2 na saída - como posso verificar dentro do meu modelo para ver se o elemento de F2 já existe na saída quando o segundo elemento F2 na fonte é processado? Meu XSLT é algo como isto no 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>

Eu preciso fazer algum tipo de verificação em todo o xsl: elemento do modelo que eu acho, mas eu não tenho certeza de como interrogar o documento de saída para ver se o elemento já está presente

.

Editar: Esqueceu os tags pre, o código deve ser visível agora

Foi útil?

Solução

Depende de como todo o sistema que você quer ser.

i. Você está preocupado apenas com elementos que são filhos do mesmo pai, ou todos os elementos ao mesmo nível ( 'primos' se quiser) ou elementos em qualquer lugar do documento ...

Na primeira situação você pode verificar o irmão anterior eixo para ver se existem quaisquer outros elementos com o mesmo nome.

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

Outras dicas

Para verificar apenas (e avisá-lo de uma segunda via), você pode encontrar um exemplo aqui

Algo ao longo das linhas de:

<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>

Para ser modificado para selecionar todos os nós dentro elemento 'root'.

Como para remover as linhas duplicadas, você tem um outro exemplo aqui

Isso seria parecido com:

<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 é a expressão XPath que você quer feito único. Pode ser concat (x, '-', @ y, '-', z) ou o que quiser.

Agora estou não tenho certeza esses dois exemplos pode ser facilmente adaptado ao seu caso, mas eu só queria salientar essas duas fontes, no caso de ajuda.

Não é possível interrogar a saída do seu transformar. Também não é possível rastrear o estado atual da sua transformação (ou seja, manter o controle do que nós que já emitida em uma variável). Fundamentalmente, isso não é como funciona a XSLT. Um dos custos de um ambiente de programação lado-free-efeito é que você não pode fazer as coisas que têm efeitos colaterais. Oh bem.

No seu caso, uma maneira de fazer isso seria construir uma variável que continha uma lista de todos os elementos de origem que poderia ser transformado no elemento de saída que pretende emitir apenas uma vez. Em seguida, verifique cada nó que você está transformando contra esta lista. Se não estiver na lista, emiti-lo. Se ele é o primeiro item na lista, emiti-lo. Caso contrário, não.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top