2 votes

XSLT 3.0 itère sur un tableau JSON enveloppé dans du XML

Je traite différents fichiers XML avec XSLT. Dans un fichier XML, j'ai trouvé une liste JSON enveloppée :

<list><![CDATA[[
    {
    "title": "Title 1",
    "value": "Value 1",
    "order": 1
    },
    {
    "title": "Title 2",
    "value": "Value 2",
    "order": 2
    }
]]]>
</list>

Mon problème est que je dois itérer sur la liste. Par exemple :

<xsl:variable name="listVar">
    <!-- do something with list -->
</xsl:variable>
<xsl:for-each select="$listVar">
    <!-- do something with objects in list e.g. -->
    <xsl:value-of select="title"/>
    <xsl:value-of select="value"/>
</xsl:for-each>

Comment faire avec XSLT ? J'utilise XSLT 3.0 et le moteur Saxon, version 9.8 HE.

Solutions envisagées :

1. Utilisation parse-json f

Mais je ne peux pas itérer sur le résultat à cause d'une XPathException : "Required item type of the context item for the child axis is node() ; supplied value (.) has item type array(function(*))" ou "Maps cannot be atomized". J'ai découvert qu'il existe des que je devrais probablement prendre en compte comme map:get, map:entry, mais je n'ai pas réussi à les utiliser dans mon cas jusqu'à présent.

2. Transformation additive avant celle mentionnée ci-dessus :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="3.0">
    <xsl:output method="xml" encoding="UTF-8" indent="no"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="list">
        <list>
            <xsl:copy-of select="json-to-xml(.)"/>
        </list>
    </xsl:template>
</xsl:stylesheet>

Et puis.. :

<xsl:variable name="listVar" select="list/array/map"/>

Mais cela ne fonctionne pas - probablement en raison de l'ajout d'un espace de noms.

<list>
    <array xmlns="http://www.w3.org/2005/xpath-functions">
        <map>
...

1voto

Martin Honnen Points 46896

Votre structure JSON lorsqu'elle est analysée avec parse-json vous donne du côté de XSLT/XPath une réseau de cartes et la façon la plus simple de traiter les éléments individuels du tableau est d'utiliser la fonction ?* opérateur de recherche Vous pouvez alors utiliser for-each ou même apply-templates :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:template match="list">
        <xsl:apply-templates select="parse-json(.)?*"/>
    </xsl:template>

    <xsl:template match=".[. instance of map(xs:string, item())]">
        <xsl:value-of select="?title, ?value"/>
    </xsl:template>
</xsl:stylesheet>

pour accéder aux valeurs de la carte, vous pouvez à nouveau utiliser ?foo comme indiqué ci-dessus.

Pour ce qui est de l'utilisation du fichier XML renvoyé par json-to-xml Il renvoie des éléments dans l'espace de noms de la fonction XPath, de sorte que pour les sélectionner, comme pour tout autre élément dans un espace de noms, vous devez vous assurer que vous avez configuré un espace de noms avec, par exemple, les éléments suivants xpath-default-namespace pour la section que vous souhaitez traiter les éléments de cet espace de noms ou vous pouvez utiliser le caractère générique de l'espace de noms, par exemple *:array/*:map .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X