将父级元素移动到子元素的循环组

时间:2013-12-10 22:42:20

标签: xml xslt

蒂姆 - 谢谢你!根据我的输入你提供的确实有效! 然而,我成了我自己的自负的受害者。我最初的输入是我的实际xml文件的结构缩小版本,我想我可以应用你的帮助的概念,最终得到我需要的东西......猜猜怎么着?即使变化很小,我仍然不能。代码的一些好的变化/调整,包括在“copy-of select =”中使用完整路径,只是不将KEY放在DOCUMENT下。它的唯一工作方式是当我使用“xsl:copy-of select =”// KEY“/”时。

我遇到的另一个问题是如何确保只有“Document”所在的“KEY”被复制到“Doc​​ument”下...使用“as is”代码,XML中的所有元素复制到每个节点(同样,只有当我使用“//”运算符时)。

请帮忙。

这是我的NOT缩小结构:

<?xml version='1.0' encoding='utf-8' ?>
<Root>
        <Level1>
                <KEY><![CDATA[keyword1]]></KEY>
                <Documents> 
                            <Document>
                                    <TYPE>type1</TYPE>
                                    <IMAGE><![CDATA[string11]]></IMAGE>
                            </Document>
                            <Document>
                                    <TYPE>type2</TYPE>
                                    <IMAGE><![CDATA[string12]]></IMAGE>
                            </Document>
                            <Document>
                                    <TYPE>type3</TYPE>
                                    <IMAGE><![CDATA[string13]]></IMAGE>
                            </Document>
                </Documents>
        </Level1>
        <Level1>
                <KEY><![CDATA[keyword2]]></KEY>
                <Documents> 
                            <Document>
                                    <TYPE>type1</TYPE>
                                    <IMAGE><![CDATA[string21]]></IMAGE>
                            </Document>
                            <Document>
                                    <TYPE>type2</TYPE>
                                    <IMAGE><![CDATA[string22]]></IMAGE>
                            </Document>
                            <Document>
                                    <TYPE>type3</TYPE>
                                    <IMAGE><![CDATA[string23]]></IMAGE>
                            </Document>
                </Documents>
        </Level1>
</Root>

我想要的结果:

<?xml version='1.0' encoding='utf-8' ?>
<Root>
        <Level1>
                <Documents> 
                            <Document>
                                    <KEY><![CDATA[keyword1]]></KEY>
                                    <TYPE>type1</TYPE>
                                    <IMAGE><![CDATA[string11]]></IMAGE>
                            </Document>
                            <Document>
                                    <KEY><![CDATA[keyword1]]></KEY>
                                    <TYPE>type2</TYPE>
                                    <IMAGE><![CDATA[string12]]></IMAGE>
                            </Document>
                            <Document>
                                    <KEY><![CDATA[keyword1]]></KEY>
                                    <TYPE>type3</TYPE>
                                    <IMAGE><![CDATA[string13]]></IMAGE>
                            </Document>
                </Documents>
        </Level1>
        <Level1>
                <Documents> 
                            <Document>
                                    <KEY><![CDATA[keyword2]]></KEY>
                                    <TYPE>type1</TYPE>
                                    <IMAGE><![CDATA[string21]]></IMAGE>
                            </Document>
                            <Document>
                                    <KEY><![CDATA[keyword2]]></KEY>
                                    <TYPE>type2</TYPE>
                                    <IMAGE><![CDATA[string22]]></IMAGE>
                            </Document>
                            <Document>
                                    <KEY><![CDATA[keyword2]]></KEY>
                                    <TYPE>type3</TYPE>
                                    <IMAGE><![CDATA[string23]]></IMAGE>
                            </Document>
                </Documents>
        </Level1>
</Root>

抱歉......再次,谢谢你。

2 个答案:

答案 0 :(得分:1)

首先,您需要阅读identity transform,看起来像这样

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

这会将所有节点复制到输出文档而不做任何更改。这意味着您只需要为需要更改的内容编写模板。

你也不应该想到移动一个元素,而是两个变化;从文档元素下删除 KEY 元素,然后添加新的 KEY 元素(即现有元素的副本)的文献

删除 KEY 元素非常简单。只是匹配它,什么都不做

<xsl:template match="KEY" />

文档元素下添加新元素也很简单。您需要一个与文档元素匹配的模板,该元素与身份模板类似,但需要额外的副本,才能从父级复制 KEY 节点。

<xsl:template match="Document">
   <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:copy-of select="../KEY" />
      <xsl:apply-templates select="node()"/>
   </xsl:copy>
</xsl:template>

因此,您复制文档元素,复制属性(如果有),从父级复制 KEY ,然后继续处理子节点。

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="KEY" />

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

编辑:作为替代方案,如果 KEY 不是父节点的子节点,但可以在任何深度,请尝试用此替换copy语句

<xsl:copy-of select="ancestor::*[KEY]/KEY" />

这应该处理任何级别的文档元素。

答案 1 :(得分:0)

好的,终于....这是蒂姆的原始xsl(经过微小的调整),这给了我想要的结果。蒂姆 - 再次感谢。 XSLT超出了我的专业领域。我只想尝试使用“准备”工具:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
  <xsl:copy>
     <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>

<xsl:template match="KEY" />

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