将连续的后代节点合并为一个 [英] Merge successive descendant nodes into one

查看:20
本文介绍了将连续的后代节点合并为一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

XML:

<t>
  <ScreenSize>
    <Width>1440</Width>
    <Height>900</Height>
  </ScreenSize>
  <ConfigurationHotSpots>
    <Rectangle>
      <Location>
        <X>0</X>
        <Y>0</Y>
      </Location>
      <Size>
        <Width>50</Width>
        <Height>50</Height>
      </Size>
      <X>0</X>
      <Y>0</Y>
      <Width>50</Width>
      <Height>50</Height>
    </Rectangle>
  </ConfigurationHotSpots>
</t>

所需的输出 XML:

<t>
  <ScreenSizeWidth>1440</ScreenSizeWidth>
  <ScreenSizeWidth>900</ScreenSizeWidth>
  <ConfigurationHotSpotsRectangleLocationX>0</ConfigurationHotSpotsRectangleLocationX>
  <ConfigurationHotSpotsRectangleLocationY>0</ConfigurationHotSpotsRectangleLocationY>
  <ConfigurationHotSpotsRectangleSizeWidth>50</ConfigurationHotSpotsRectangleSizeWidth>
  <ConfigurationHotSpotsRectangleSizeHeight>50</ConfigurationHotSpotsRectangleSizeHeight>
  <ConfigurationHotSpotsRectangleX>0</ConfigurationHotSpotsRectangleX>
  <ConfigurationHotSpotsRectangleY>0</ConfigurationHotSpotsRectangleY>
  <ConfigurationHotSpotsRectangleWidth>50</ConfigurationHotSpotsRectangleWidth>
  <ConfigurationHotSpotsRectangleHeight>50</ConfigurationHotSpotsRectangleHeight>
</t>

规则:

  • 对于已定义节点集中的每个元素(在本例中为 | ),执行以下操作:处理所有叶子后代(即没有子节点的后代),使得创建新元素;这个新元素的名称应该是当前节点和无子后代之间所有元素的串联.
  • 在整个文档中这些块"的数量是可变的,因此没有手动模板(即只处理 的后代的模板,仅处理 <ScreenSize> 的后代的模板> 等)
  • For every element in a defined nodeset (in this case <ScreenSize> | <ConfigurationHotSpots>), do the following: process all leaf descendants (i.e., those without children) such that a new element is created; the name of this new element should be the concatenation of all elements between the current node and the childless descendant.
  • There is a variable number of these "blocks" throughout the document, so no manual templates (i.e., one that processes only descendants of <ScreenSize>, one that processes only descendants of <ConfigurationHotSpots>, etc.)

我目前拥有的:

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

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

  <xsl:template match="ScreenSize|ConfigurationHotSpots">
    <xsl:apply-templates select="descendant::*[not(*)]" mode="descendants" />
  </xsl:template>

  <xsl:template match="*" mode="descendants">
    <xsl:element name="{concat(name(ancestor::*[not(self::t)]), name())}">
      <xsl:apply-templates />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

问题似乎出在 name(ancestor::*[not(self::t)]) 部分;它没有做我希望它做的事情(神奇地一个接一个地输出这些元素的名称).相反,这就是我得到的:

The problem seems to be the name(ancestor::*[not(self::t)]) portion; it's not doing what I would like it to be doing (magically outputting the names of those elements, one after another). Instead, this is what I get:

<?xml version="1.0" encoding="UTF-8"?>
<t>
  <ScreenSizeWidth>1440</ScreenSizeWidth>
  <ScreenSizeHeight>900</ScreenSizeHeight>
  <ConfigurationHotSpotsX>0</ConfigurationHotSpotsX>
  <ConfigurationHotSpotsY>0</ConfigurationHotSpotsY>
  <ConfigurationHotSpotsWidth>50</ConfigurationHotSpotsWidth>
  <ConfigurationHotSpotsHeight>50</ConfigurationHotSpotsHeight>
  <ConfigurationHotSpotsX>0</ConfigurationHotSpotsX>
  <ConfigurationHotSpotsY>0</ConfigurationHotSpotsY>
  <ConfigurationHotSpotsWidth>50</ConfigurationHotSpotsWidth>
  <ConfigurationHotSpotsHeight>50</ConfigurationHotSpotsHeight>
</t>

提前致谢!

推荐答案

Doing name(ancestor::*[not(self::t)]) 不会返回名称列表,但是只是它匹配的最后一个的名称(还是第一个?).

Doing name(ancestor::*[not(self::t)]) will not return a list of names, but just the name of the last one it matches (or is it the first?).

您可以采取的一种稍微不同的方法,与您目前正在做的相差不远,而不是直接跳到叶"元素,依次匹配每个级别,但保持元素名称的连续连接,通过参数从一层传递到另一层.

A slightly different approach you can take, not that far off from what you are currently doing, is rather than jumping straight to the 'leaf' element, match each level in turn, but keep a running concatenation of the element names, which are passed from one level to anoter by parameters.

试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="ScreenSize|ConfigurationHotSpots">
        <xsl:apply-templates mode="descendants">
            <xsl:with-param name="name" select="local-name()" />
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="*" mode="descendants">
        <xsl:param name="name" />
        <xsl:apply-templates mode="descendants">
            <xsl:with-param name="name" select="concat($name, local-name())" />
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="*[not(*)]" mode="descendants">
        <xsl:param name="name" />
        <xsl:element name="{concat($name, local-name())}">
            <xsl:value-of select="." />
        </xsl:element>
    </xsl:template>

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

当应用于您的示例 XML 时,输出如下

When applied to your sample XML, the following is output

<t>
   <ScreenSizeWidth>1440</ScreenSizeWidth>
   <ScreenSizeHeight>900</ScreenSizeHeight>
   <ConfigurationHotSpotsRectangleLocationX>0</ConfigurationHotSpotsRectangleLocationX>
   <ConfigurationHotSpotsRectangleLocationY>0</ConfigurationHotSpotsRectangleLocationY>
   <ConfigurationHotSpotsRectangleSizeWidth>50</ConfigurationHotSpotsRectangleSizeWidth>
   <ConfigurationHotSpotsRectangleSizeHeight>50</ConfigurationHotSpotsRectangleSizeHeight>
   <ConfigurationHotSpotsRectangleX>0</ConfigurationHotSpotsRectangleX>
   <ConfigurationHotSpotsRectangleY>0</ConfigurationHotSpotsRectangleY>
   <ConfigurationHotSpotsRectangleWidth>50</ConfigurationHotSpotsRectangleWidth>
   <ConfigurationHotSpotsRectangleHeight>50</ConfigurationHotSpotsRectangleHeight>
</t>

这篇关于将连续的后代节点合并为一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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