XSLT - 根据其他属性的值复制某些属性

Posted

技术标签:

【中文标题】XSLT - 根据其他属性的值复制某些属性【英文标题】:XSLT- Copying certain attributes based on the value of other attributes 【发布时间】:2019-07-09 15:30:19 【问题描述】:

我有以下 XML 示例:

<?xml version="1.0" encoding="UTF-8"?>
<languages>
    <language lang='english' source='1'/>
    <language lang='english' source='2'/>
    <language lang='french' target='1' new1-fr='56' new2-fr='66'/>
    <language lang='german' target='1' new1-ger='20' new2-ger='21'/>
    <language lang='norwegian' target='2' new3-no='76' new2-no='15'/>
    <language lang='norwegian' target='1' new1-no='30'></language>
    <language lang='german' target='2' new1-ger='23' new2-ger='24' new3-ger='25'/>
</languages>

我想做的是: 当语言元素的@target(@lang=french|german|norwegian)与语言的@source(@lang='english)'相同时,将它们的属性(所有以'new'开头)作为属性复制到元素语言 lang='english'

它应该是这样的:

<languages>
    <language lang='english' source='1' new1-fr='56' new2-fr='66' new1-ger='20' new2-ger='21' new1-no='30'/>
    <language lang='english' source='2' new3-no='76' new2-no='15' new1-ger='23' new2-ger='24' new3-ger='25'/>
</languages>

非常感谢您的帮助。

【问题讨论】:

你到底在哪里坚持这个? 如果您不知道从哪里开始,请从 identity transform 开始,使用 @target 添加匹配 language 的 xsl:key,添加匹配 language[@source] 的模板以输出语言元素并将模板应用于当前属性以及匹配键的属性 (key('lang',@source)/@*)。您可能还需要添加一个与需要剥离的内容匹配的空模板 (language[@target]|language[@target]/@lang|@target)。 【参考方案1】:

由于您已经接受了答案而没有显示您的尝试,我将继续添加基于我的评论的替代方案...

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="lang" match="language" use="@target"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="language[@source]">
    <xsl:copy>
      <xsl:apply-templates select="@*|key('lang',@source)/@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="language[@target]|language[@target]/@lang|@target"/>

</xsl:stylesheet>

小提琴:http://xsltfiddle.liberty-development.net/gWvjQf2

【讨论】:

【参考方案2】:

您可以使用以下模板。第一个只负责复制根节点

<xsl:template match="languages">
   <xsl:copy>
       <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
</xsl:template>

第二个匹配所有具有@source 属性的language 元素。然后它在复制源元素的所有属性和@target 属性等于$src 变量的language 元素的所有属性之前复制元素本身——不包括名称为lang 和@987654328 的属性@。

<xsl:template match="language[@source]">
    <xsl:variable name="src" select="@source" />
    <xsl:copy>
        <xsl:copy-of select="@* | ../language[@target=$src]/@*[not(local-name(.) ='target') and not(local-name(.) ='lang')]"/>
    </xsl:copy>
</xsl:template>

【讨论】:

以上是关于XSLT - 根据其他属性的值复制某些属性的主要内容,如果未能解决你的问题,请参考以下文章

XSLT 仅在存在其他子节点属性时更改子节点

XSLT 替换属性值和文本节点中的文本

计算属性或其他方式根据 Vue 中 v-for 中的值更改样式

获取元素的值并使其成为 XSLT 中属性的值?

使用命名空间时无法在 XSLT 中复制和修改属性

XSLT - 如何仅输出属性值并忽略元素的值