XSLT - 将父节点复制到子节点中

问题描述 投票:0回答:2

我需要将父节点的副本移动到多个子节点中,而无需在此过程中复制所述子节点本身。这是一个示例 XML:

<FoodGroups>
   <Nutritional>Yes</Nutritional>
   <Artifical>No</Artificial>
   <FoodGroup>
      <Fruit>Grape</Fruit>
      <Fruit>Apple</Fruit>
   </FoodGroup>
   <FoodGroup>
      <Vegetable>Carrot</Vegetable>
      <Vegetable>Potato</Vegetable>
   <FoodGroup>
</FoodGroups>

转换完成后,我需要 XML 如下所示:

<xml>
   <FoodGroup>
      <Fruit>Grape</Fruit>
      <Fruit>Apple</Fruit>
      <FoodGroups>
         <Nutritional>Yes</Nutritional>
         <Articial>No</Artificial>
      </FoodGroups>
   </FoodGroup>
   <FoodGroup>
      <Vegetable>Carrot</Vegetable>
      <Vegetable>Potato</Vegetable>
      <FoodGroups>
         <Nutritional>Yes</Nutritional>
         <Articial>No</Artificial>
      </FoodGroups>
   <FoodGroup>
</xml>

我试过使用以下 XML:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output omit-xml-declaration="yes"
method="xml"
indent="yes"/>

<xsl:template match="/">
<xml>
<xsl:copy>
    <xsl:apply-templates select="//FoodGroup"/>
</xsl:copy>
</xml>
</xsl:template>

<xsl:template match="//FoodGroup">
<FoodGroup>
    <xsl:copy-of select="./*"/>
    <xsl:copy-of select="//FoodGroups/*[not(child::FoodGroup)]"/>
</FoodGroup>
</xsl:template>

</xsl:stylesheet>

但是,我得到以下输出(子节点完全重新复制——我不想要这个):

<xml>
   <FoodGroup>
      <Fruit>Grape</Fruit>
      <Fruit>Apple</Fruit>
      <FoodGroups>
         <Nutritional>Yes</Nutritional>
         <Artifical>No</Artificial>
         <FoodGroup>
            <Fruit>Grape</Fruit>
            <Fruit>Apple</Fruit>
         </FoodGroup>
         <FoodGroup>
            <Vegetable>Carrot</Vegetable>
            <Vegetable>Potato</Vegetable>
         <FoodGroup>
      </FoodGroups>
   </FoodGroup>
   <FoodGroup>
      <Vegetable>Carrot</Vegetable>
      <Vegetable>Potato</Vegetable>
      <FoodGroups>
         <Nutritional>Yes</Nutritional>
         <Artifical>No</Artificial>
         <FoodGroup>
            <Fruit>Grape</Fruit>
            <Fruit>Apple</Fruit>
         </FoodGroup>
         <FoodGroup>
            <Vegetable>Carrot</Vegetable>
            <Vegetable>Potato</Vegetable>
         <FoodGroup>
      </FoodGroups>
   <FoodGroup>
</xml>

这种亲子复制能做吗?是否可以?部分困难在于,有时这些孩子的深度不止一层。

xml xslt xslt-1.0
2个回答
0
投票

以下似乎可以完成这项工作:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="/">
    <xml>
      <xsl:apply-templates/>
    </xml>
  </xsl:template>
  
  <xsl:template match="FoodGroups">
    <xsl:apply-templates/>
  </xsl:template>
  
  <xsl:template match="FoodGroups/*[not(self::FoodGroup)]"/>
  
  <xsl:template match="FoodGroup">
    <xsl:copy>
      <xsl:apply-templates/>
      <FoodGroups>
        <xsl:copy-of select="ancestor::FoodGroups/*[not(self::FoodGroup)]"/>
      </FoodGroups>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

0
投票

为什么不简单(而且更有效):

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/FoodGroups">
    <xml>
        <xsl:variable name="common" select="*[not(self::FoodGroup)]" />
        <xsl:for-each select="FoodGroup">
            <xsl:copy>
                <xsl:copy-of select="*"/>
                <FoodGroups>
                    <xsl:copy-of select="$common"/>
                </FoodGroups>
            </xsl:copy>
        </xsl:for-each>
    </xml>
</xsl:template>

</xsl:stylesheet>
© www.soinside.com 2019 - 2024. All rights reserved.