2011-07-12 15 views
6

devo duplicare il payload XML in altrettanti payload XML sulla base di uno specifico ID, ad esempio, useridcome duplicare elementi XML

<ns2:Details xmlns:ns2="ns"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>46</ns2:UserId> 
    <ns2:UserId>237</ns2:UserId> 
</ns2:Details> 

ho bisogno l'uscita come

<ns2:Details> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>46</ns2:UserId> 
</ns2:Details> 
<ns2:Details> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>237</ns2:UserId> 
</ns2:Details> 

è questo possibile


Update: La risposta di seguito che è stato dato è workin Va bene, ma c'è un piccolo problema che non ho menzionato. Se l'ID utente è lo stesso e si sta ripetendo, dovrebbe essere visualizzato lo stesso payload xml. Per questo ho provato quanto segue per ottenere gli elementi unici di userid

<xsl:param name="userId" select="ns0:UserId[generate-id(.)=generate-id(key('k', ns0:UserId)[1])]"/> 

ma questo non funziona e anche provato a usare sopra

..[generate-id(.)=generate-id(key('k', ns0:UserId)[1])] 

a livello di modello anche non funziona

Am Mi manca qualcosa?

Aggiornamento: ho fatto una piccola modifica al codice precedente, invece di lavorare a xsl: param, ho usato a xsl: applicare-template

prima modifica (fornito come risposta per me) < xsl: apply-templates select = "// ns2: Details/ns2: UserId" /> dopo la modifica < xsl: apply-templates select = "// ns2: Dettagli/ns2: UserId [genera- id (.) = generate-id (chiave ('myUserId',.) [1])] "/>

errore mio stavo usando ns2: userid invece di "."

codice XSL piena ---

<xsl:output method="xml" indent="yes"/> <xsl:key name="k" match="ns2:UserId" use="text()"/> <xsl:key name="myUserId" match="ns2:UserId" use="."/> <xsl:template match="/"> <ns2:Root> <xsl:apply-templates select="//ns2:Details/ns2:UserId[generate-id(.)=generate-id(key('myUserId', .)[1])]"/> </ns2:Root> </xsl:template>

<xsl:template match="//ns2:Details"> <xsl:param name="userId" select="ns2:UserId"/> <ns2:Details> <xsl:copy-of select="key('k', $userId)[1]"/> <!-- displays UserId values--> <xsl:copy-of select="./*[name() != 'ns2:UserId']"/> <!-- displays other values--> </ns2:Details> </xsl:template>

<xsl:template match="ns2:UserId"> <xsl:apply-templates select=".."> <xsl:with-param name="userId" select="."/> </xsl:apply-templates> </xsl:template>

prega, convalidarlo. anche questo funziona per me ...

+2

Your input e output desiderato non sono ben formate. Presumo che ' Organizzazione' dovrebbe essere ' Organizzazione'? – Jacqueline

+0

+1 per bella domanda. Non capisco davvero il tuo _update_. Vuoi ripetere 'UserId' per generare altri' Dettagli'? La mia risposta funziona bene per te? –

+0

Ok, vedo, ho aggiornato la mia risposta per rimuovere i duplicati. –

risposta

3

XML Supposed:

<ns2:Details xmlns:ns2="ns2"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>46</ns2:UserId> 
    <ns2:UserId>237</ns2:UserId> 
    <ns2:UserId>46</ns2:UserId> 
</ns2:Details> 

XSLT:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ns2="ns2" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:key name="k" match="ns2:UserId" use="text()"/> 

    <xsl:template match="/"> 
    <root> 
     <xsl:apply-templates select="//ns2:Details/ns2:UserId[not(node() = preceding-sibling::node())]"/> 
    </root> 
    </xsl:template> 

    <xsl:template match="//ns2:Details"> 
    <xsl:param name="userId" select="ns2:UserId"/> 

    <ns2:Details> 
     <xsl:copy-of select="key('k', $userId)[not(node() = preceding-sibling::node())]"/> 
     <xsl:copy-of select="./*[name() != 'ns2:UserId']"/> 
    </ns2:Details> 
    </xsl:template> 

    <xsl:template match="ns2:UserId"> 
    <xsl:apply-templates select=".."> 
     <xsl:with-param name="userId" select="."/> 
    </xsl:apply-templates> 
    </xsl:template> 

</xsl:stylesheet> 

XML in uscita:

<?xml version="1.0" encoding="utf-8"?> 
<root xmlns:ns2="ns2"> 
    <ns2:Details> 
    <ns2:UserId>46</ns2:UserId> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    </ns2:Details> 
    <ns2:Details> 
    <ns2:UserId>237</ns2:UserId> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    </ns2:Details> 
</root> 
+0

+1 - buona risposta e tu mi hai appena battuto :) – Jacqueline

0

Sì, è possibile. È possibile eseguire il ciclo utilizzando un for-each loop utilizzando per ogni nodo ns2: ID utente.

0

Un modo per ottenere il risultato desiderato è quello di utilizzare la trasformazione Identità e di override il nodo ns2:Details.

Nel modello di sostituzione, è possibile utilizzare l'istruzione di ripetizione xsl:for-each per iterare su tutto UserId.

Per gestire il duplicato UserId è possibile utilizzare il noto predicato derivante dal metodo di raggruppamento menuchiano.

Perché useremo la trasformazione dell'identità, il modo in cui tutto viene generato è molto più semplice.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ns2="ns"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="UserId" match="ns2:UserId" use="."/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ns2:Details"> 
     <xsl:for-each select="ns2:UserId 
         [generate-id() 
         = generate-id(key('UserId',.)[1])]"> 
      <ns2:Details> 
       <xsl:copy-of select="../@*"/> 
       <xsl:apply-templates select="../node() 
        [not(self::ns2:UserId)]"/> 
       <xsl:apply-templates select="."/> 
      </ns2:Details> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

Quando questa trasformazione viene applicato all'ingresso fornito in questione, il seguente frammento si ottiene:

<ns2:Details xmlns:ns2="ns"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>46</ns2:UserId> 
</ns2:Details> 
<ns2:Details xmlns:ns2="ns"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>237</ns2:UserId> 
</ns2:Details> 

Questa uscita si ottiene anche quando duplicati di UserId sono presenti nel documento di input.

0

Il seguente foglio di stile gestisce i duplicati:

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:ns2="ns2"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:key name="byUserId" match="ns2:UserId" use="." /> 
    <xsl:template match="/"> 
     <root> 
      <xsl:apply-templates 
       select="ns2:Details/ns2:UserId 
        [generate-id()=generate-id(key('byUserId', .)[1])]" /> 
     </root> 
    </xsl:template> 
    <xsl:template match="ns2:UserId"> 
     <xsl:apply-templates select=".." mode="out"> 
      <xsl:with-param name="userId" select="." /> 
     </xsl:apply-templates> 
    </xsl:template> 
    <xsl:template match="ns2:Details" mode="out"> 
     <xsl:param name="userId" select="''" /> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*" mode="out" /> 
      <xsl:copy-of select="$userId"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="ns2:UserId" mode="out" /> 
    <xsl:template match="node()|@*" mode="out"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*" mode="out" /> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

Su questo ingresso:

<ns2:Details xmlns:ns2="ns2"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>46</ns2:UserId> 
    <ns2:UserId>237</ns2:UserId> 
    <ns2:UserId>46</ns2:UserId> 
</ns2:Details> 

produce:

<root xmlns:ns2="ns2"> 
    <ns2:Details> 
     <ns2:var1>AA0511201143</ns2:var1> 
     <ns2:var2>PARCEL</ns2:var2> 
     <ns2:var3>04/04/2011</ns2:var3> 
     <ns2:var4>Organization</ns2:var4> 
     <ns2:UserId>46</ns2:UserId> 
    </ns2:Details> 
    <ns2:Details> 
     <ns2:var1>AA0511201143</ns2:var1> 
     <ns2:var2>PARCEL</ns2:var2> 
     <ns2:var3>04/04/2011</ns2:var3> 
     <ns2:var4>Organization</ns2:var4> 
     <ns2:UserId>237</ns2:UserId> 
    </ns2:Details> 
</root> 
1

Questa trasformazione (breve, solo due modelli, senza xsl:for-each , nessuna modalità):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="ns"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kIdByVal" match="ns2:UserId" use="."/> 

<xsl:template match="/"> 
    <xsl:apply-templates select= 
    "ns2:Details/ns2:UserId 
     [generate-id()=generate-id(key('kIdByVal',.)[1])] 
    "/> 
</xsl:template> 

<xsl:template match="ns2:UserId"> 
    <ns2:Details> 
    <xsl:copy-of select= 
    "../node() 
      [not(self::ns2:UserId 
       [not(generate-id()=generate-id(current()))]) 
      ]"/> 
    </ns2:Details> 
</xsl:template> 
</xsl:stylesheet> 

quando applicato su questo documento XML (contenenti ridondanti ns2:UserId elementi):

<ns2:Details xmlns:ns2="ns"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>46</ns2:UserId> 
    <ns2:UserId>237</ns2:UserId> 
    <ns2:UserId>46</ns2:UserId> 
</ns2:Details> 

produce esattamente la desiderata, risultato corretto:

<ns2:Details xmlns:ns2="ns"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>46</ns2:UserId> 
</ns2:Details> 
<ns2:Details xmlns:ns2="ns"> 
    <ns2:var1>AA0511201143</ns2:var1> 
    <ns2:var2>PARCEL</ns2:var2> 
    <ns2:var3>04/04/2011</ns2:var3> 
    <ns2:var4>Organization</ns2:var4> 
    <ns2:UserId>237</ns2:UserId> 
</ns2:Details> 

Spiegazione: Raggruppamento di Muenchian, xsl:copy-of, uso di

0

IN aggiunta a quello in XSLT 2.0 è semplice Invece di scrivere più modelli con modelli di applicazione, vedere il codice sottostante con modello singolo darà lo stesso risultato.

<xsl:for-each-group select="*:Details" group-by="*:UserId"> 


     <xsl:comment select="current-grouping-key()"/> 


     <ns2:Details> 


      <xsl:for-each select="current-group()"> 


       <xsl:element name="ns2:UserId"> 


        <xsl:value-of select="current-grouping-key()"/> 
       </xsl:element> 


       <xsl:copy-of select="*[name() != 'ns2:UserId']"/> 


      </xsl:for-each> 


     </ns2:Details> 


    </xsl:for-each-group> 


</xsl:template>