【问题标题】:Handle excluded element in a foreach处理 foreach 中的排除元素
【发布时间】:2021-08-19 08:15:00
【问题描述】:

在第一个模板中,我有意排除了一个元素(“牛奶”),因为解析的数据映射相对平坦,我想使用 XSLT 对数据进行分类和结构化。目的是处理第二个模板中的排除元素(“牛奶”)。这两个模板一次运行一个。一起运行模板不会显示排除元素('milk')的结果,它应该设置另一个属性名称和属性值。

JSON:

<data>
{
  "storage": {
    "pencils": 12,
    "milk": 8,
    "rulers": 4
  }
}
</data>

XSL:

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

<xsl:transform
  version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:storage="http://www.exammple.com/1"
  xmlns:office="http://www.exammple.com/2"
  xmlns:item="http://www.exammple.com/3"
  expand-text="yes">

  <xsl:output method="xml" indent="yes"/>

  <xsl:mode on-no-match="shallow-skip"/>

  <!-- Parse JSON to XML -->

  <xsl:template match="data">
    <storage:one>
      <xsl:apply-templates select="json-to-xml(.)"/>
    </storage:one>
  </xsl:template>

  <!-- Print map -->
  <!-- <xsl:template match="*[@key = 'storage']"> <xsl:copy-of select=".."/> </xsl:template> -->

  <xsl:template match="*[@key='storage']">

      <xsl:for-each select="*[not(@key='milk')]">
      <xsl:element name="item:{@key}">
        <xsl:attribute name="office">plant-1</xsl:attribute>
        <xsl:value-of select="text()"/>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="*[@key='milk']">
      <xsl:for-each select=".">
      <xsl:element name="item:{@key}">
        <xsl:attribute name="beverage">plant-2</xsl:attribute>
        <xsl:value-of select="text()"/>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>

</xsl:transform>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<storage:one xmlns:item="http://www.exammple.com/3"
             xmlns:office="http://www.exammple.com/2"
             xmlns:storage="http://www.exammple.com/1">
   <item:pencils office="plant-1">12</item:pencils>
   <item:rulers office="plant-1">4</item:rulers>
</storage:one>

想要的结果:

<?xml version="1.0" encoding="UTF-8"?>
<storage:one xmlns:item="http://www.exammple.com/3"
             xmlns:office="http://www.exammple.com/2"
             xmlns:storage="http://www.exammple.com/1">
   <item:pencils office="plant-1">12</item:pencils>
   <item:rulers office="plant-1">4</item:rulers>
   <item:milk beverage="plant-2">8</item:milk>
</storage:one>

【问题讨论】:

  • 在我看来,通过将模板和应用模板与嵌套的 for-each 混合使用,您似乎让您的生活变得困难。为什么不尝试编写模板并仅依赖应用模板。而且如前所述,做for-each select="." 毫无意义。

标签: json xml xslt xslt-3.0


【解决方案1】:

您的第二个模板永远不会匹配,因为它永远不会到达。所有元素都由 &lt;xsl:template match="*[@key='storage']"&gt; 处理 - 它没有 &lt;xsl:apply-templates ...&gt; 来访问更多模板。

您的第一个模板不会递归到其子级。所以在第一个模板的末尾添加一个&lt;xsl:apply-templates select="*" /&gt;

    <xsl:template match="*[@key='storage']">
      <xsl:for-each select="*[not(@key='milk')]">
        <xsl:element name="item:{@key}">
          <xsl:attribute name="office">plant-1</xsl:attribute>
          <xsl:value-of select="text()"/>
        </xsl:element>
      </xsl:for-each>
      <xsl:apply-templates select="*" />
    </xsl:template>

这将尝试在“存储”级别应用更多模板,因此匹配第二个模板。

【讨论】:

    【解决方案2】:

    我会为每种不同的输出类型编写模板,如果输出的顺序与输入的顺序不同,则在 xsl:sort 或 XPath 3.1 sort 调用中更改顺序:

      <xsl:template match="data">
        <storage:one>
          <xsl:apply-templates select="json-to-xml(.)"/>
        </storage:one>
      </xsl:template>
      
      <xsl:template match="*[@key = 'storage']">
        <xsl:apply-templates select="sort(*, (), function($el) { $el/@key = 'milk' })"/>
      </xsl:template>
    
      <xsl:template match="*[@key='storage']/*[not(@key='milk')]">
          <xsl:element name="item:{@key}">
            <xsl:attribute name="office">plant-1</xsl:attribute>
            <xsl:value-of select="text()"/>
          </xsl:element>
      </xsl:template>
    
      <xsl:template match="*[@key='storage']/*[@key='milk']">
          <xsl:element name="item:{@key}">
            <xsl:attribute name="beverage">plant-2</xsl:attribute>
            <xsl:value-of select="text()"/>
          </xsl:element>
      </xsl:template>
    

    【讨论】:

      猜你喜欢
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 2019-11-14
      • 2014-12-10
      • 1970-01-01
      相关资源
      最近更新 更多