首页 > 解决方案 > 如何使用 name() 动态应用模板?

问题描述

我正在将 XSLT 从源 XML 转换为 JSON。我希望将数组类型元素转换为“元素:[]”

从给定的 xslt 我匹配节点名称并应用模板。但是如何为每个数组类型元素动态地执行此操作,或者我可以选择需要将哪个元素转换为 JSON 中的数组类型元素。

这是我的源 XML

<order>
  <email>mark.h@yopmail.com</email>
<tax-lines>
    <tax-line>
      <title>CGST</title>
      <price>29.00</price>
      <rate>0.2</rate>
    </tax-line>  
  </tax-lines>

  <freight-Lines>
    <freight-Line>
      <title>CGST</title>
      <price>29.00</price>
      <rate>0.2</rate>
    </freight-Line>
  </freight-Lines>
</order>

XSLT:

  <xsl:when test="name()= 'tax-lines'">
         [<xsl:apply-templates select="*" mode="ArrayElement"/>] 
      </xsl:when>

使用它,我将输出 Json 设置为:

    {

    "order" :
        {

    "email" :"mark.h@yopmail.com",
    "tax-lines" :
         [
        {

    "title" :"CGST",
    "price" :"29.00",
    "rate" :"0.2"
        }
      ] 

        }
      }

无论如何我可以动态地对'freight-Lines'数组做同样的事情吗?意味着我想动态地做这条线

<xsl:when test="name()= 'tax-lines'">
         [<xsl:apply-templates select="*" mode="ArrayElement"/>] 
      </xsl:when>

标签: xmlxslt

解决方案


解决此问题的一种方法是使用某种映射模式来控制转换。所以你可能有:

由此您可能会生成一个包含一组模板规则的样式表,例如:

<xsl:template match="tax-lines | freight-lines">
  <xsl:text>[</xsl:text>
  <xsl:for-each select="*">
    <xsl:if test="position() != 1">,</xsl:if>
    <xsl:apply-templates select="."/>
  <xsl:text>]</xsl:text>
</xsl:template>

<xsl:template match="tax-line | freight-line">
  <xsl:text>{</xsl:text>
  <xsl:for-each select="*">
    <xsl:if test="position() != 1">,</xsl:if>
    <xsl:text>"</xsl:text>
    <xsl:value-of select="local-name()"/>
    <xsl:text>":</xsl:text>
    <xsl:apply-templates select="."/>
  <xsl:text>}</xsl:text>
</xsl:template>

<xsl:template match="*[. castable as xs:double]">
  <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="*">
  <xsl:text>"</xsl:text>
  <xsl:value-of select="."/>
  <xsl:text>"</xsl:text>
</xsl:template>

因此,您基本上有一组用于将不同 XML 元素映射到 JSON 的模式,每个模式都有一个框架模板规则;您的映射模式定义了用于源文档中每个元素的模式(默认),然后您将映射模式转换为将每个元素名称与相应模板规则相关联的样式表。


推荐阅读