Saltar al contenido principal

Ejercicio 517

Consideremos el siguiente documento XML.

Diseña el fichero XSLT que permita obtener el siguiente documento XML:

<?xml version="1.0" encoding="utf-8"?>
<usuarios>
<usuario id="u01" nick="perez90">
<nombre>Juan Pérez</nombre>
<apps>
<app id="a01" pegi="+3">WhatsApp Messenger</app>
<app id="a07" pegi="+12">Twitter</app>
<app id="a09" pegi="+3">Google Maps</app>
</apps>
</usuario>
<usuario id="u02" nick="gnz-98">
<nombre>María González</nombre>
<apps>
<app id="a19" pegi="+3">Waze</app>
<app id="a16" pegi="+3">Adobe Photoshop Express</app>
</apps>
</usuario>
<usuario id="u03" nick="pablo.r">
<nombre>Pablo Ruiz</nombre>
<apps>
<app id="a01" pegi="+3">WhatsApp Messenger</app>
<app id="a03" pegi="+12">YouTube</app>
<app id="a04" pegi="+12">Facebook</app>
</apps>
</usuario>
<usuario id="u04" nick="sofia95">
<nombre>Sofía Díaz</nombre>
<apps>
<app id="a11" pegi="+3">Google Drive</app>
<app id="a08" pegi="+3">WhatsApp Business</app>
</apps>
</usuario>
<usuario id="u05" nick="luisa_gomez">
<nombre>Luisa Gómez</nombre>
<apps>
<app id="a05" pegi="+12">TikTok</app>
<app id="a06" pegi="+12">Netflix</app>
<app id="a07" pegi="+12">Twitter</app>
<app id="a08" pegi="+3">WhatsApp Business</app>
</apps>
</usuario>
<usuario id="u06" nick="carlos7">
<nombre>Carlos Ramírez</nombre>
<apps>
<app id="a20" pegi="+3">Candy Crush Saga</app>
</apps>
</usuario>
</usuarios>
Solución

Hoja XSL:

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

<xsl:template match="/">
<usuarios>
<xsl:for-each select="//usuario">
<usuario>
<xsl:attribute name="id" select="@id"/>
<xsl:attribute name="nick" select="nick"/>
<nombre><xsl:value-of select="nombre"/></nombre>
<apps>
<xsl:for-each select="apps/app">
<xsl:variable name="id" select="@id"/>
<app>
<xsl:attribute name="id" select="@id"/>
<xsl:attribute name="pegi" select="/android/aplicaciones/app[@id=$id]/pegi"/>
<xsl:value-of select="/android/aplicaciones/app[@id=$id]/titulo"/>
</app>
</xsl:for-each>
</apps>
</usuario>
</xsl:for-each>
</usuarios>
</xsl:template>
</xsl:stylesheet>

Hoja XSL (alternativa):

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

<xsl:template match="/">
<usuarios>
<xsl:for-each select="//usuario">
<usuario id="{@id}" nick="{nick}">
<nombre><xsl:value-of select="nombre"/></nombre>
<apps>
<xsl:for-each select="apps/app">
<xsl:variable name="id" select="@id"/>
<app id="@id" pegi="{/android/aplicaciones/app[@id=$id]/pegi}">
<xsl:value-of select="/android/aplicaciones/app[@id=$id]/titulo"/>
</app>
</xsl:for-each>
</apps>
</usuario>
</xsl:for-each>
</usuarios>
</xsl:template>
</xsl:stylesheet>

Hoja XSL (alternativa sin utilizar variables):

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

<xsl:template match="/">
<usuarios>
<xsl:for-each select="//usuario">
<usuario id="{@id}" nick="{nick}">
<nombre><xsl:value-of select="nombre"/></nombre>
<apps>
<xsl:for-each select="apps/app">
<app id="@id" pegi="{/android/aplicaciones/app[@id=current()/@id]/pegi}">
<xsl:value-of select="/android/aplicaciones/app[@id=current()/@id]/titulo"/>
</app>
</xsl:for-each>
</apps>
</usuario>
</xsl:for-each>
</usuarios>
</xsl:template>
</xsl:stylesheet>

En esta última solución se utiliza la función current(), la cual permite referenciar al nodo actual dentro de la expresión XPath del bucle for-each y deshacer la ambigüedad.