【问题标题】:How to use for-each element as parameter to a template如何使用 for-each 元素作为模板的参数
【发布时间】:2019-03-03 13:18:15
【问题描述】:

我知道标题听起来不太能描述我的问题。让我在下面进一步解释。

我有一个返回 JSON 数组的 java 应用程序,我的目标是将此结果解析为字符串格式,以便在另一个“C”应用程序中使用,这两个应用程序之间唯一可能的通信是字符串格式。

我已经使用 XSLT 通过硬编码我在 JSON 响应中寻找的值来实现这一点,这就是我的做法。

我的 XML 是:

<?xml version="1.0" encoding="UTF-8"?>
<input>[{"media_key":"1-1UL-12528","media_value":"10 RUE DES TRELISSAC","media_type":"Courrier"},{"media_key":"2-1UL-12528","media_value":"0614263770","media_type":"SMS"}]</input>

我的 XSL 是:

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:template match="input">
    <output>
        <xsl:call-template name="print-object-values">
            <xsl:with-param name="string" select="."/>
        </xsl:call-template>
    </output>
</xsl:template>

<!-- Recupere la valeur d'une cle json String de type "key":"val" -->
<xsl:template name="get_string_json">
    <xsl:param name = "json" />
    <xsl:param name = "key" />

    <xsl:variable name="needle">
        <xsl:value-of select="concat('&quot;', $key, '&quot;:&quot;')" />
    </xsl:variable>

    <xsl:value-of select="substring-before(substring-after($json, $needle), '&quot;')" />
</xsl:template>


<xsl:template name="print-object-values">
    <xsl:param name="string"/>
    <xsl:param name="sep_values" select="';'" />

    <xsl:if test="contains($string,'media_key')">
        <xsl:text>|</xsl:text>

        <!-- Partie à modifier en récupérant les valeurs désiré par les fonctions déclarer prècedemment -->
        <xsl:call-template name="get_string_json">
            <xsl:with-param name="json" select="$string" />
            <xsl:with-param name="key" select="'media_key'" />
        </xsl:call-template>
        <xsl:value-of select="$sep_values" />
        <xsl:call-template name="get_string_json">
            <xsl:with-param name="json" select="$string" />
            <xsl:with-param name="key" select="'media_type'" />
        </xsl:call-template>
        <xsl:value-of select="$sep_values" />
        <xsl:call-template name="get_string_json">
            <xsl:with-param name="json" select="$string" />
            <xsl:with-param name="key" select="'media_value'" />
        </xsl:call-template>

        <xsl:call-template name="print-object-values">
            <xsl:with-param name="string" select="substring-after($string,'&quot;},{')"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

在我的 print-object-values 模板中,我使用 print-object-values 来获取 JSON 字符串中特定键的值。

我想要做的不是对我正在搜索的字符串进行硬编码,有没有办法在变量中将其实现为映射,然后在 for-each 循环中使用它来执行 get_string_json ?

编辑:

这是我想要实现的示例

<xsl:template match="input">
    <output>
        <xsl:variable name="values">  <!-- declaration of the values to search for -->
            <value>
                <param>media_key</param>
                <param>media_type</param>
                <param>media_value</param>
            </value> 
        </xsl:variable>

        <xsl:call-template name="print-object-values">
            <xsl:with-param name="string" select="."/>
        </xsl:call-template>
    </output>
</xsl:template>

<xsl:template name="get_string_json">
    <xsl:param name = "json" />
    <xsl:param name = "key" />

    <xsl:variable name="needle">
        <xsl:value-of select="concat('&quot;', $key, '&quot;:&quot;')" />
    </xsl:variable>

    <xsl:value-of select="substring-before(substring-after($json, $needle), '&quot;')" />
</xsl:template>


<xsl:template name="print-object-values">
    <xsl:param name="string"/>
    <xsl:param name="sep_values" select="';'" />

    <xsl:if test="contains($string,'media_key')">
        <xsl:text>|</xsl:text>

        <xsl:for-each select= ><!-- select params in the variable values -->
            <xsl:call-template name="get_string_json">
                <xsl:with-param name="json" select="$string" />
                <xsl:with-param name="key" select="" /><!-- pass the value of the param -->
            </xsl:call-template>
        </xsl:for-each>
        <xsl:call-template name="print-object-values">
            <xsl:with-param name="string" select="substring-after($string,'&quot;},{')"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

【问题讨论】:

  • XSLT 3 与 XPath 3.1 具有类似 parse-json w3.org/TR/xpath-functions/#func-parse-json 的功能,因此使用 Saxon 9.8 或更高版本,您可以使用纯 XSLT/XPath 解析和处理 JSON,而无需尝试在 XSLT 中编写 JSON 解析器。
  • 我是 XSLT 的新手,在我的应用程序中,我只找到了如何将 XSLT 1.0 实现到现有代码,我不知道我是否可以轻松切换到 XSLT 3,正在更改版本从 1.0 到 3.0 就够了,还是我需要重写部分代码?
  • 您需要使用像 Saxon 9.8 或 9.9 这样的 XSLT 3 处理器,因此在 Java 世界 (mvnrepository.com/artifact/net.sf.saxon/Saxon-HE) 或 .NET (nuget.org/packages/Saxon-HE) 中很容易,因为有开源这些平台的 Saxon 9.8 或 9.9 版本。您没有展示或解释您如何使用 XSLT,因此无法说明您必须更改什么。
  • 首先,谢谢马丁的回答。我只需要指定我无权访问 java 应用程序代码,我不能只更改 XSL。我是一家公司的实习生,该公司使用 XSL 将 HTTP 响应转换为字符串值,然后将其发送到 C 应用程序以供进一步使用。 JSON 在 XML 响应中。我的解决方案是功能性的,我已经对其进行了测试,并且像魅力一样工作,但它总是需要对我在模板中寻找的值进行硬编码。我需要的是一种遍历数组或 XML 变量的方法,并为每个元素调用模板
  • 循环、数组?好吧,祝你好运。

标签: json xslt


【解决方案1】:

重要提示:
此答案的目的是解决您问题的这一部分:

而不是硬编码我的字符串 搜索,有没有办法在变量中实现这个作为地图 然后在 for-each 循环中使用它来执行 get_string_json ?

我发现有必要对您的 XSLT 的其他部分进行一些调整,但我没有检查您解析 JSON 的方法。

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />

<!-- declaration of the values to search for -->
<xsl:variable name="keys">  
    <key>media_key</key>
    <key>media_type</key>
    <key>media_value</key>
</xsl:variable>

<xsl:template match="input">
    <output>
        <xsl:call-template name="print-object-values">
            <xsl:with-param name="string" select="."/>
        </xsl:call-template>
    </output>
</xsl:template>

<xsl:template name="print-object-values">
    <xsl:param name="string"/>
    <xsl:param name="separator" select="'&quot;},{'" />

    <xsl:variable name="object" select="substring-before(concat($string, $separator), $separator)" />

    <xsl:text>|</xsl:text>

    <!-- HERE IS THE RELEVANT PART -->
    <xsl:for-each select="exsl:node-set($keys)/key">
        <xsl:call-template name="get_string_json">
            <xsl:with-param name="json" select="concat($object, '&quot;')" />
            <xsl:with-param name="key" select="." />
        </xsl:call-template>
        <xsl:if test="position()!=last()">
            <xsl:text>;</xsl:text>
        </xsl:if>
    </xsl:for-each>

    <xsl:if test="contains($string, $separator)">
        <xsl:call-template name="print-object-values">
            <xsl:with-param name="string" select="substring-after($string, $separator)"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<!-- Recupere la valeur d'une cle json String de type "key":"val" -->
<xsl:template name="get_string_json">
    <xsl:param name = "json" />
    <xsl:param name = "key" />

    <xsl:variable name="needle">
        <xsl:value-of select="concat('&quot;', $key, '&quot;:&quot;')" />
    </xsl:variable>

    <xsl:value-of select="substring-before(substring-after($json, $needle), '&quot;')" />
</xsl:template>

</xsl:stylesheet>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多