首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >XSLT -如何存储从源文档中删除的一组元素以供重用

XSLT -如何存储从源文档中删除的一组元素以供重用
EN

Stack Overflow用户
提问于 2019-03-27 01:57:02
回答 2查看 81关注 0票数 0

给定以下XML:

代码语言:javascript
复制
<root>
  <group>
    <e1>001</e1>
    <e2>beep</e2>
    <e2>bop</e2>
    <e2>ork</e2>
    <e2>ah</e2>
    <e2>ah</e2>
  </group>
  <group>
    <e1>002</e1>
    <e2>beep</e2>
    <e2>bop</e2>
    <e2>ork</e2>
    <e2>ah</e2>
    <e2>ah</e2>
  </group>
  <group>
    <e1>003</e1>
    <e2>beep</e2>
    <e2>bop</e2>
    <e2>ork</e2>
    <e2>ah</e2>
    <e2>ah</e2>
  </group>
  <group>
    <e1>004</e1>
    <e2>beep</e2>
    <e2>bop</e2>
    <e2>ork</e2>
    <e2>ah</e2>
    <e2>ah</e2>
  </group>
</root>

请注意,每个“组”元素中的“e2”元素都是相同的,这在源文档中是有保证的。

我正在尝试使用XSLT来完成以下步骤:

  1. 保存一组'e2‘元素的副本,
  2. 擦除所有’e2‘元素,
  3. 创建一组默认的组元素,并将一组e2s插入其中

所需的输出将如下所示:

代码语言:javascript
复制
<root>
  <group>
    <e1>default1</e1>
    <e2>beep</e2>
    <e2>bop</e2>
    <e2>ork</e2>
    <e2>ah</e2>
    <e2>ah</e2>
  </group>
  <group>
    <e1>default2</e1>
    <e2>beep</e2>
    <e2>bop</e2>
    <e2>ork</e2>
    <e2>ah</e2>
    <e2>ah</e2>
  </group>
</root>

源文档中的'e1‘值是不相关的,而输出文档中的'e2’值是预先知道的,并且是静态的。只有'e2‘值是动态的,我需要确保它们都在那里。

我以前在用一些硬编码值替换所有元素时使用过类似的模式:

代码语言:javascript
复制
<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*"/>
  </xsl:copy>
</xsl:template>

<!-- Empty Template eliminates all but first 'group' element. -->
<xsl:template match="//group[preceding::group]"></xsl:template>

<xsl:template match="//group">
  <xsl:element name="group">
    <e1>default1</e1>           
    <!-- e2 elements inserted here somehow? -->
  </xsl:element>
  <xsl:element name="group">
    <e1>default2</e1>           
    <!-- e2 elements inserted here somehow? -->
  </xsl:element>
</xsl:template>

我尝试将这些元素存储到变量中,但没有插入任何内容到输出html中:

代码语言:javascript
复制
<xsl:variable name="e2Elements" select="//group[1]/e2"></xsl:variable>
<xsl:template match="//group">
  <xsl:element name="group">
    <e1>default1</e1>           
    <xsl:copy-of select="$e2Elements" />
  </xsl:element>
</xsl:template>

但是我不确定如何将e2元素插入到值中。我使用的是SaxonHE9.8N,可以访问exslt命名空间和xslt2.0

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-27 03:59:31

您的解决方案实际上是制作了一个不必要的元素副本。您可以在不复制它们的情况下完成此操作,如下所示:

代码语言:javascript
复制
<xsl:variable name="e3Elements" select="//group[1]/e2" />

另一个低效是使用前一个轴的<xsl:template match="group[preceding::group]"/>总是很昂贵,尤其是在模式中。明显的改进是将其替换为前置兄弟(搜索前置兄弟轴比搜索前置同级轴快得多)。但实际上,您可以做得更好:将此规则设为组的默认规则(<xsl:template match="group"/>),并使另一个规则仅与第一个组(<xsl:template match="group[1]">...)匹配。

但实际上,也不需要匹配第一个group元素,因为您没有使用它的任何数据。

在风格上,<group><xsl:element name="group">更受欢迎,因为它的可读性更好。

这将是我的XSLT 3.0解决方案:

代码语言:javascript
复制
<xsl:transform version="3.0" .... expand-text="yes">

  <xsl:template match="/">
    <xsl:variable name="e3Elements" select="//group[1]/e2"/>
    <xsl:for-each select="'default1', 'default2'">
      <group>
        <e1>{.}</e1>
        <xsl:copy-of select="$e3Elements"/>
      </group>
    </xsl:for-each>
  </xsl:template>

</xsl:transform>
票数 2
EN

Stack Overflow用户

发布于 2019-03-27 03:32:20

最后,我需要使用copy-of使我的变量成为元素的副本。下面是我的解决方案:

代码语言:javascript
复制
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

<xsl:variable name="e3Elements">
    <xsl:copy-of select="//group[1]/e2" />
</xsl:variable>

<xsl:template match="group[preceding::group]"></xsl:template>

<xsl:template match="group">
    <xsl:element name="group">
        <xsl:element name="e1">default1</xsl:element>
        <xsl:copy-of select="$e3Elements"></xsl:copy-of>
    </xsl:element>
    <xsl:element name="group">
        <xsl:element name="e1">default2</xsl:element>
        <xsl:copy-of select="$e3Elements"></xsl:copy-of>
    </xsl:element>
</xsl:template>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55363510

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档