微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在现有元素上应用属性集

如何解决在现有元素上应用属性集

处理具有相对扁平层次树结构的导入 JSON 数据。 在当前代码中,我在创建元素期间应用了属性集。

是否可以先创建所有元素,然后再应用属性集? 似乎“use-attribute-sets”是一个属性,因此需要添加到元素上才能工作。

我当前的代码中没有错误消息。

我只是想看看是否可以按如下所述的特定顺序进行操作。 之所以进行这样的改动,是为了处理更大的数据量,先进行元素的解析和创建,然后再通过属性集统一添加属性

我拥有的序列:

[1] Create attribute sets. 
[2] Group element names. 
[3] Parse JSON to XML map. 
[4] Build element,using attribute-sets and extract key value

我想执行的序列:

[1] Create attribute sets (same as above).
[2] Group element names (same as above).
[3] Parse JSON to XML map (same as above).
[4] Build element names with corresponding key (split of above bullet 4).
[5] Add attribute-set based on template match in the code (split of above bullet 4).

JSON:

<data>
{
  "store": {
    "pencils": 43,"milk": 21,"rulers": 12,"beer": 17
  }
}
</data>

XSL:

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

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:inventory="http://www.example.org/1"
  xmlns:item="http://www.example.org/2"
  expand-text="yes"
>

  <xsl:output method="xml" indent="yes"/>
  <xsl:mode on-no-match="shallow-skip"/>

  <!-- [1] Create attribute sets -->

  <xsl:attribute-set name="group-office">
    <xsl:attribute name="contextRef">office</xsl:attribute>
  </xsl:attribute-set>

  <!-- [2] Group element names-->

  <xsl:param name="group-office">pencils,rulers</xsl:param>
  <xsl:param name="attributes-for-group-office" select="tokenize($group-office,',\s*')"/>

  <!-- [3] Parse JSON to XML -->

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

  <!-- [4] Build element,using attribute-sets and extract key value -->

  <xsl:template match="*[@key = 'store']/*[@key = $attributes-for-group-office]">
    <xsl:for-each select=".">
      <xsl:element name="item:{@key}" use-attribute-sets="group-office">
        <xsl:value-of select="text()"/>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>

</xsl:transform>

结果 (当前以及代码序列更改后的样子):

<?xml version="1.0" encoding="UTF-8"?>
<inventory:store xmlns:inventory="http://www.example.org/1"
                 xmlns:item="http://www.example.org/2">
   <item:pencils contextRef="office">43</item:pencils>
   <item:rulers contextRef="office">12</item:rulers>
</inventory:store>

解决方法

这是一个相当人为且不是很容易的分离,因为您无法在不创建元素的情况下注入属性集,因此您可以做的所有事情,如果有帮助,请编写一个具有高优先级的模板来选择元素名称并通过将其转移到期望该名称作为参数的较低层,然后像以前一样执行实际工作以创建具有属性集的元素:

  <!-- [4] Extract key value for element name -->

  <xsl:template match="*[@key = 'store']/*[@key = $attributes-for-group-office]" priority="10">
    <xsl:next-match>
      <xsl:with-param name="element-name" select="'item:' || @key"/>
    </xsl:next-match>
  </xsl:template>
  
  <!-- [5] Build element and add attribute-set based on template match in the code -->

  <xsl:template match="*[@key = 'store']/*[@key = $attributes-for-group-office]" priority="5">
    <xsl:param name="element-name" required="yes"/>
    <xsl:element name="{$element-name}" use-attribute-sets="group-office">
      <xsl:value-of select="text()"/>
    </xsl:element>
  </xsl:template>

我不确定分离是否有意义,但如果你真的想要两个独立的模板,我暂时想不出别的办法。当然,Siebe 使用临时树的基于模式的建议也是一种选择,但需要该临时树;或者你可以使用上面的,而不是依靠优先级来确保处理顺序使用一种模式并推动同一个节点通过,对我来说感觉就像以前一样人为和困难的分离:

  <!-- [4] Build element and extract key value -->

  <xsl:template match="*[@key = 'store']/*[@key = $attributes-for-group-office]">
    <xsl:apply-templates select="." mode="add-attribute-sets">
      <xsl:with-param name="element-name" select="'item:' || @key"/>
    </xsl:apply-templates>
  </xsl:template>
  
  <!-- [5] Build element and add attribute-set based on template match in the code -->

  <xsl:template match="*[@key = 'store']/*[@key = $attributes-for-group-office]" mode="add-attribute-sets">
    <xsl:param name="element-name" required="yes"/>
    <xsl:element name="{$element-name}" use-attribute-sets="group-office">
      <xsl:value-of select="text()"/>
    </xsl:element>
  </xsl:template>
,

您可以像这样使用模式(添加了一些元素以明确所需的阶段):

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

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:inventory="http://www.example.org/1"
  xmlns:item="http://www.example.org/2"
  expand-text="yes"
  >
  
  <xsl:output method="xml" indent="yes"/>
  <xsl:mode on-no-match="shallow-skip"/>
  <xsl:mode name="useAttributeSet" on-no-match="shallow-skip"/>
  
  <!-- [1] Create attribute sets -->
  
  <xsl:attribute-set name="group-office">
    <xsl:attribute name="contextRef">office</xsl:attribute>
  </xsl:attribute-set>
  
  <!-- [2] Group element names-->
  
  <xsl:param name="group-office">pencils,rulers</xsl:param>
  <xsl:param name="attributes-for-group-office" select="tokenize($group-office,',\s*')"/>
  
  <!-- [3] Parse JSON to XML -->
  
  <xsl:template match="data">
    <xsl:variable name="withoutAttributeSets">
      <xsl:apply-templates select="json-to-xml(.)/*"/>
    </xsl:variable>
    <stages>
      <stage>
        <inventory:store>
          <xsl:copy-of select="$withoutAttributeSets"/>
        </inventory:store>
      </stage>
      <stage>
        <inventory:store>
          <xsl:apply-templates select="$withoutAttributeSets" mode="useAttributeSet"/>
        </inventory:store>
      </stage>
    </stages>
  </xsl:template>
  
  <!-- [4] Build element names with corresponding key (split of above bullet 4). -->
  
  <xsl:template match="*[@key = 'store']/*[@key = $attributes-for-group-office]">
    <xsl:for-each select=".">
      <xsl:element name="item:{@key}" >
        <xsl:value-of select="text()"/>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>
  
  <!-- [5] Add attribute-set based on template match in the code (split of above bullet 4). -->

  <xsl:template match="*[local-name() = $attributes-for-group-office]" mode="useAttributeSet">
  <xsl:element name="{name()}" use-attribute-sets="group-office">
      <xsl:value-of select="text()"/>
    </xsl:element>
  </xsl:template>

</xsl:transform>

结果如下:

<?xml version="1.0" encoding="UTF-8"?>
<stages xmlns:inventory="http://www.example.org/1"
        xmlns:item="http://www.example.org/2">
   <stage>
      <inventory:store>
         <item:pencils>43</item:pencils>
         <item:rulers>12</item:rulers>
      </inventory:store>
   </stage>
   <stage>
      <inventory:store>
         <item:pencils contextRef="office">43</item:pencils>
         <item:rulers contextRef="office">12</item:rulers>
      </inventory:store>
   </stage>
</stages>

根据您的需要进行调整。

如果你想以其他方式重用这个 [4]-stage,你也可以这样保存:

<xsl:result-document href="stage-4.xml">
  <inventory:store>
    <xsl:copy-of select="$withoutAttributeSets"/>
  </inventory:store>
</xsl:result-document>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。