首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将所有子节点复制为-is-is to产生的树?

如何将所有子节点复制为-is-is to产生的树?
EN

Stack Overflow用户
提问于 2012-03-25 17:41:28
回答 2查看 12.6K关注 0票数 1

UPDATE (破坏者):这个问题已经得到回答(请参阅下面的),它看起来像是JRE中某些版本中包含的XSLT实现中的一个bug (就像它在jdk中工作,但在jre 1.6.0_20-b02上不工作,在1.6.0_31-B05时根本不工作)。我在Oracle站点上记录了一个bug。

我马上就到了,就功能而言,它现在起作用了。但我不满意其中的一些部分,其中一些(我相信)可能会更短。这就是问题..。详情见下文

这是一个输入xml的例子

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<t1>
    <t2 a1="v1">
        <ot1 a2="v2" />
        <ot2 a3="v3">
            <t3 a5="v4">
                <ot1 a2="v5" />
            </t3>
        </ot2>
    </t2>
</t1>

-这是预期结果xml的一个示例(请参阅下面的xslt文件,以获得关于的线索)。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<t1>
    <t2 a1="v1">
        <gt2 a="ot2" b="gtv1">
            <gt1 a="ot1">v2</gt1>
        </gt2>
        <gt2 a="ot2" b="v3">
            <t3 a5="v4">
                <gt2 a="ot2" b="gtv1">
                    <gt1 a="ot1">v5</gt1>
                </gt2>
            </t3>
        </gt2>
    </t2>
</t1>

--这是我最终得到的xslt (但不太高兴)。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exslt="http://exslt.org/common" version="1.0"
    exclude-result-prefixes="exslt">
    <xsl:output method="xml" />

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

    <xsl:template match="ot1|ot2">
        <xsl:variable name="thisResult">
            <xsl:apply-templates select="." mode="impl" />
        </xsl:variable>
        <xsl:apply-templates select="exslt:node-set($thisResult)" />
    </xsl:template>

    <xsl:template match="ot1" mode="impl">
        <ot2 a3="gtv1">
            <gt1 a="ot1">
                <xsl:value-of select="@a2" />
            </gt1>
        </ot2>
    </xsl:template>

    <xsl:template match="ot2" mode="impl">
        <gt2 a="ot2" b="{@a3}">
            <xsl:for-each select="child::*">
                <xsl:element name="{name()}">
                    <xsl:copy-of select="@*|node()" />
                </xsl:element>
            </xsl:for-each>
        </gt2>
    </xsl:template>
</xsl:stylesheet>

的问题是:如何缩短时间?

代码语言:javascript
复制
<xsl:for-each select="child::*">
    <xsl:element name="{name()}">
        <xsl:copy-of select="@*|node()" />
    </xsl:element>
</xsl:for-each>

我尝试了以下方法,但在本例中,部分结果xml将丢失(特别是gt2元素的属性将丢失)

代码语言:javascript
复制
<xsl:copy-of select="node()"/>

也试过

代码语言:javascript
复制
<xsl:copy-of select="*"/>

没有成功

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-25 18:27:54

Dimitre展示了另一种策略,但是要在您最初的帖子中回答这个问题,xsl:for-each是(除了这里没有显示的一些命名空间效果之外)相当于一个单独的

代码语言:javascript
复制
<xsl:copy-of select="*"/>

如果用这个替换xsl:for-每个输出,则得到相同的输出。

你建议的替换

代码语言:javascript
复制
<xsl:copy-of select="node()"/>

几乎相同,但获取用于缩进源的空白节点,因此输出在空白中有所不同。

你说

(特别是gt3元素的属性将丢失)

但是,编码更改不会改变属性,并且示例输入或输出中没有gt3元素?

票数 2
EN

Stack Overflow用户

发布于 2012-03-25 18:09:36

我需要定义xslt转换,它能够执行所谓的“多传递转换”。

这里没有必要使用多通道处理.

这个简短而简单的转换:

代码语言:javascript
复制
<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="ot1">
  <gt1 a="ot1"><xsl:value-of select="@a2"/></gt1>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="ot2">
  <gt2 a="ot2" b="{@a3}"/>
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用时

代码语言:javascript
复制
<t1>
    <t2 a1="v1">
        <ot1 a2="v2" />
        <ot2 a3="v3">
            <t3 a5="v4">
                <ot1 a2="v5" />
            </t3>
        </ot2>
    </t2>
</t1>

生成想要的、正确的结果

代码语言:javascript
复制
<t1>
   <t2 a1="v1">
      <gt1 a="ot1">v2</gt1>
      <gt2 a="ot2" b="v3"/>
      <t3 a5="v4">
         <gt1 a="ot1">v5</gt1>
      </t3>
   </t2>
</t1>

UPDATE:OP更新了他认为需要多通处理的问题--这仍然是不正确的。

这里是这个新问题的一个简短的简单解决方案,同样是在一个简单的

代码语言:javascript
复制
<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="ot1">
  <gt2 a="ot2" b="gtv{substring-after(name(), 'ot')}">
    <gt1 a="ot1"><xsl:value-of select="@a2"/></gt1>
  </gt2>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="ot2">
  <gt2 a="ot2" b="{@a3}"/>
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于新提供的XML源文档时的

代码语言:javascript
复制
<t1>
    <t2 a1="v1">
        <ot1 a2="v2" />
        <ot2 a3="v3">
            <t3 a5="v4">
                <ot1 a2="v5" />
            </t3>
        </ot2>
    </t2>
</t1>

再一次想要的,正确的结果产生

代码语言:javascript
复制
<t1>
   <t2 a1="v1">
      <gt2 a="ot2" b="gtv1">
         <gt1 a="ot1">v2</gt1>
      </gt2>
      <gt2 a="ot2" b="v3"/>
      <t3 a5="v4">
         <gt2 a="ot2" b="gtv1">
            <gt1 a="ot1">v5</gt1>
         </gt2>
      </t3>
   </t2>
</t1>

UPDATE2:由于OP要求对他当前的代码进行重构,特别需要更好地表达以下摘录:

这里有一个明显的重构--只需用替换上面的

代码语言:javascript
复制
<xsl:apply-templates/>

修改后的,完整的代码变成

代码语言:javascript
复制
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:exslt="http://exslt.org/common" version="1.0"
        exclude-result-prefixes="exslt">
        <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="ot1|ot2">
            <xsl:variable name="thisResult">
                <xsl:apply-templates select="." mode="impl" />
            </xsl:variable>
            <xsl:apply-templates select=
            "exslt:node-set($thisResult)" />
        </xsl:template>

        <xsl:template match="ot1" mode="impl">
            <ot2 a3="gtv1">
                <gt1 a="ot1">
                    <xsl:value-of select="@a2" />
                </gt1>
            </ot2>
        </xsl:template>

        <xsl:template match="ot2" mode="impl">
            <gt2 a="ot2" b="{@a3}">
                <xsl:apply-templates/>
            </gt2>
        </xsl:template>
</xsl:stylesheet>

,以及当应用于最新提供的源XML文档

代码语言:javascript
复制
<t1>
    <t2 a1="v1">
        <ot1 a2="v2" />
        <ot2 a3="v3">
            <t3 a5="v4">
                <ot1 a2="v5" />
            </t3>
        </ot2>
    </t2>
</t1>

想要的结果是

代码语言:javascript
复制
<t1>
   <t2 a1="v1">
      <gt2 a="ot2" b="gtv1">
         <gt1 a="ot1">v2</gt1>
      </gt2>
      <gt2 a="ot2" b="v3">
         <t3 a5="v4">
            <gt2 a="ot2" b="gtv1">
               <gt1 a="ot1">v5</gt1>
            </gt2>
         </t3>
      </gt2>
   </t2>
</t1>
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9862437

复制
相关文章

相似问题

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