XSLT:根据其他元素的存在添加具有可变数量的子元素的新节点
我试图根据XML中其他元素的存在性来添加具有可变数量的子元素的新节点文件。这里是我开始用一个简单的例子:XSLT:根据其他元素的存在添加具有可变数量的子元素的新节点
输入:
<Parent>
<FirstChild>
<List>
<!--There could be an unlimited number of different Fruit elements in this list-->
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
<!--...-->
</List>
</FirstChild>
</Parent>
我需要添加一个新的节点(父/ SecondChild),与基于元素创建的子元素在列表节点中。输出应该是这样的(减去我的意见!):
所需的输出:
<Parent>
<FirstChild>
<List>
<!--There could be an unlimited number of Fruit elements in this list-->
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
<!--...-->
</List>
</FirstChild>
<SecondChild>
<NewList>
<!--A separate <NewFruit> element needs to be added below based on the existence of the <Fruit> elements in <List> above-->
<NewFruit A="Apples"/>
<NewFruit B="Bananas"/>
<!--...-->
</NewList>
</SecondChild>
</Parent>
我知道如何添加SecondChild节点,并使用变换像子元素:
变换:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" exclude-result-prefixes="xs fn xdt">
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Parent">
<Parent>
<xsl:apply-templates select="@*|*"/>
<SecondChild>
<NewList>
</NewList>
</SecondChild>
</Parent>
</xsl:template>
</xsl:stylesheet>
这给出了以下的输出:
电流输出:
<Parent>
<FirstChild>
<List>
<!--There could be an unlimited number of Fruit elements in this list-->
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
<!--...-->
</List>
</FirstChild>
<SecondChild>
<NewList>
<!--HELP!-->
</NewList>
</SecondChild>
</Parent>
但我在一个不知如何创建NewFruit子元素(在我的帮助!评论是)动态地基于存在水果元素FirstChild节点。任何援助将非常感激 - 我只是不知道在这一点上走什么方向。
UPDATE:
我的问题的回答工作了我提供的XML(谢谢!),但它不工作了,我实际使用XML(我不能粘贴的保密原因)。下面正是模仿了XML我一起工作的格式:
输入:
<Parent>
<Level1>
<Level2>
<List>
<!--There could be an unlimited number of different Fruit elements in this list-->
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
</List>
</Level2>
<NewLevel2>
</NewLevel2>
</Level1>
</Parent>
我需要添加一个新的节点(父母/ 1级/ NewLevel2/NewNode),一些子元素是基于列表节点中的元素创建的。输出应该是这样的:
所需的输出:
<Parent>
<Level1>
<Level2>
<List>
<!--There could be an unlimited number of Fruit elements in this list-->
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
</List>
</Level2>
<NewLevel2>
<NewNode>
<NewChildNode>
<NewChildNode1/>
<NewList>
<!--A separate <NewFruit> element needs to be added below based on the existence of the <Fruit> elements in <List> above-->
<NewFruit A="Apples"/>
<NewFruit B="Bananas"/>
</NewList>
</NewChildNode>
</NewNode>
</NewLevel2>
</Level1>
</Parent>
这是我使用XSLT:
变换:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" exclude-result-prefixes="xs fn xdt">
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="NewLevel2">
<NewLevel2>
<xsl:apply-templates select="@*|*"/>
<NewNode>
<NewChildNode>
<NewChildNode1/>
<NewList>
<xsl:for-each select="*/List/Fruit">
<NewFruit>
<xsl:apply-templates select="@*|node()"/>
</NewFruit>
</xsl:for-each>
</NewList>
</NewChildNode>
</NewNode>
</NewLevel2>
</xsl:template>
</xsl:stylesheet>
这使以下输出:
电流输出:
<Parent>
<Level1>
<Level2>
<List>
<!--There could be an unlimited number of different Fruit elements in this list-->
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
</List>
</Level2>
<NewLevel2>
<NewNode>
<NewChildNode>
<NewChildNode1/>
<NewList/>
</NewChildNode>
</NewNode>
</NewLevel2>
</Level1>
</Parent>
所以NewList元素是空的 - 不被某种原因产生的NewFruit子节点。但是,我不明白为什么这不起作用,当我发布的原始XML确实转换正确?
如下您可以调整XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"
exclude-result-prefixes="xs fn xdt">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Parent">
<Parent>
<xsl:apply-templates select="@*|*"/>
<SecondChild>
<NewList>
<xsl:for-each select="*/List/Fruit">
<NewFruit>
<xsl:apply-templates select="@* | node()"/>
</NewFruit>
</xsl:for-each>
</NewList>
</SecondChild>
</Parent>
</xsl:template>
</xsl:stylesheet>
结果:
<Parent>
<FirstChild>
<List>
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
<!--...-->
</List>
</FirstChild>
<SecondChild>
<NewList>
<NewFruit A="Apples"/>
<NewFruit B="Bananas"/>
</NewList>
</SecondChild>
</Parent>
更新:当你更新你的问题(输入XML以及所需的输出),以下调整XSLT提供了新的所需输出:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"
exclude-result-prefixes="xs fn xdt">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Parent">
<Parent>
<xsl:apply-templates select="@*|*"/>
</Parent>
</xsl:template>
<xsl:template match="NewLevel2">
<NewLevel2>
<NewNode>
<NewChildNode>
<NewChildNode1/>
<NewList>
<xsl:for-each select="//Parent//List/Fruit">
<NewFruit>
<xsl:apply-templates select="@*|node()"/>
</NewFruit>
</xsl:for-each>
</NewList>
</NewChildNode>
</NewNode>
</NewLevel2>
</xsl:template>
</xsl:stylesheet>
XML输入:
<Parent>
<Level1>
<Level2>
<List>
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
</List>
</Level2>
<NewLevel2>
</NewLevel2>
</Level1>
</Parent>
XML输出:
<Parent>
<Level1>
<Level2>
<List>
<Fruit A="Apples"/>
<Fruit B="Bananas"/>
</List>
</Level2>
<NewLevel2>
<NewNode>
<NewChildNode>
<NewChildNode1/>
<NewList>
<NewFruit A="Apples"/>
<NewFruit B="Bananas"/>
</NewList>
</NewChildNode>
</NewNode>
</NewLevel2>
</Level1>
</Parent>
如前所述由michael.hor257k评论,您的模板匹配NewLevel2
不会产生任何输出NewLevel2
只是一个空您的输入XML中的元素。因此,要获得所需的输出,只需调整XSLT以使其模板与空NewLevel2
相匹配,该模板将生成NewLevel2
的输出,而不是用于此模板的当前节点(该模板为空),但是用于根的果实列表 - <xsl:for-each select="//Parent//List/Fruit">
。
非常感谢!这个解决方案完全适用于我提供的XML,但是当我在我的实际XML上尝试时,它没有正确转换。所以我做了我的XML格式的精确副本,并在原始问题中粘贴更新,如果您不介意再看一下?再次,我真的很感谢你的帮助。 – lcf0285 2014-10-03 03:32:32
@ lcf0285很高兴我能够帮助你。我刚更新了我更新问题的答案。 – 2014-10-03 07:54:53
我不明白你的问题。你说“基于XML文档中其他元素的存在”。 “其他地方”究竟在哪里?我在源XML中只看到一个列表。什么 - 如果有的话 - 应该是输出中两个列表之间的区别? – 2014-10-03 03:22:38
(在你编辑之后)我仍然不明白你的问题。你只是试图在输出的两个地方复制相同的列表,还是应该在两者之间有所不同? – 2014-10-03 03:42:58
请注意,在您的输入中没有'NewLevel2'元素,因此''不匹配任何内容,因此也不会执行任何操作。 **所以你目前的输出不是你说的那样。** –
2014-10-03 03:48:41