递归连接父属性 [英] Concatenate parent attributes recursively

查看:26
本文介绍了递归连接父属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下 XML:

<package>
    <node name="a">
        <node name="b"/>
        <node name="c"/>
        <node name="d">
            <node name="e"/>
            <node name="f"/>
            <node name="g">
                <node name="h"/>
            </node>
        </node>    
    </node>
</package>

我基本上想在连接每个父 node 元素的 name 属性的同时压平树,直到最后一个 node 元素:

I basically want to flatten the tree while concatenating the name attributes of each parent node element until the last node element:

<package>
    <node name="a-b"/>
    <node name="a-c"/>
    <node name="a-d-e"/>
    <node name="a-d-f"/>
    <node name="a-d-g-h"/>
</package>

到目前为止我所做的是使用模板和 xsl:copy-of 正确生成所有 node 元素的平面列表:

What I got working so far is is properly generating a flat list of all node elements using a template and xsl:copy-of:

<xsl:template match="//node">
    <xsl:copy-of select="current()"/>
</xsl:template>

这给了我:

<package>
    <node name="b"/>
    <node name="c"/>
    <node name="e"/>
    <node name="f"/>
    <node name="h"/>
</package>

但我不确定如何正确地从这里继续.我的目的是扩展模板并使用 xsl:attributexsl:for-each 来连接和修改属性:

But I'm not sure how to properly continue from here. My intention was to extend the template and using xsl:attribute and xsl:for-each to concatenate and modify the attribute:

    <xsl:template match="node/@name">
        <xsl:attribute name="name">
            <xsl:for-each select="ancestor::node">
                <xsl:if test="position() > 1">.</xsl:if>
                <xsl:value-of select="@name"/>
            </xsl:for-each>
        </xsl:attribute>
    </xsl:template>

然而,这只会打印 node 的数据(如果有的话).我在这里错过了什么?

However, this only prints the node's data (if any). What am I missing here?

我有可用的 XSLT 2.0,我的灵感来自于这个 SO 问题.

I have XSLT 2.0 available and I got my inspiration from this SO question.

推荐答案

我基本上想在连接名称的同时展平树每个父节点元素的属性,直到最后一个节点元素:

I basically want to flatten the tree while concatenating the name attributes of each parent node element until the last node element:

这是一个完整且有效的 XSLT 2.0 解决方案:

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

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

  <xsl:template match="node[*]"><xsl:apply-templates/></xsl:template>

  <xsl:template match="node[not(*)]/@name">
    <xsl:attribute name="name" select="string-join(../ancestor-or-self::node/@name, '-')"/>
  </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<package>
    <node name="a">
        <node name="b"/>
        <node name="c"/>
        <node name="d">
            <node name="e"/>
            <node name="f"/>
            <node name="g">
                <node name="h"/>
            </node>
        </node>
    </node>
</package>

产生想要的、正确的结果:

<package>
   <node name="a-b"/>
   <node name="a-c"/>
   <node name="a-d-e"/>
   <node name="a-d-f"/>
   <node name="a-d-g-h"/>
</package>

<小时>

二.XSLT 1.0 解决方案:

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

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

  <xsl:template match="node[*]"><xsl:apply-templates/></xsl:template>

  <xsl:template match="node[not(*)]/@name">
    <xsl:attribute name="name"><xsl:apply-templates select="." mode="gen"/></xsl:attribute>
  </xsl:template>

  <xsl:template match="node/@name" mode="gen">
    <xsl:apply-templates select="../parent::node/@name" mode="gen"/>
    <xsl:if test="../parent::node">-</xsl:if>
    <xsl:value-of select="."/>
  </xsl:template>
</xsl:stylesheet>

在同一个 XML 文档(上图)上应用此转换时,会产生相同的正确结果:

<package>
   <node name="a-b"/>
   <node name="a-c"/>
   <node name="a-d-e"/>
   <node name="a-d-f"/>
   <node name="a-d-g-h"/>
</package>

这篇关于递归连接父属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆