Xslt将元素复制到现有元素,如果不存在,则创建新元素
对xml转换非常陌生,我一直在做(可能对您来说)非常简单的工作。 让我们建议我们有来源:Xslt将元素复制到现有元素,如果不存在,则创建新元素,xslt,Xslt,对xml转换非常陌生,我一直在做(可能对您来说)非常简单的工作。 让我们建议我们有来源: <root> <someValue>123</someValue> </root> 123 应将其转化为: <root> <additional> <someValue>123</someValue> </additional> </root> 123 但如果我们
<root>
<someValue>123</someValue>
</root>
123
应将其转化为:
<root>
<additional>
<someValue>123</someValue>
</additional>
</root>
123
但如果我们有这个来源:
<root>
<additional>
<b>something</b>
</additional>
<someValue>123</someValue>
</root>
某物
123
我们应该将某个值移动到现有的附加值,即:
<root>
<additional>
<b>something</b>
<someValue>123</someValue>
</additional>
</root>
某物
123
请记住,a级别上可能有其他元素具有相同的行为(移动到附加下)。
很好,工作示例非常受欢迎,但如果它附带有对其工作原理的小描述,那将是非常棒的(我更喜欢钓鱼,而不是仅仅被喂食)。一种可能的方法是添加一个
附加的包装器作为根的子对象,并删除现有的附加
包装器-使其子级向上移动,成为根
的子级(或者更确切地说,是添加的附加
包装器的子级):
XSLT1.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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root">
<xsl:copy>
<additional>
<xsl:apply-templates/>
</additional>
</xsl:copy>
</xsl:template>
<xsl:template match="additional">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node() except someValue"/>
</xsl:copy>
</xsl:template>
<xsl:template match="additional">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:copy-of select="following-sibling::someValue"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我的结局如下:
<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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/additional"/>
<xsl:template match="/root">
<xsl:copy>
<additional>
<xsl:copy-of select="someValue"/>
<xsl:copy-of select="additional/*"/>
</additional>
</xsl:copy>
</xsl:template>
在这里,我们剥离原始的附加的,然后从头开始创建它,复制需要的someValue和源文件中的原始内容(附加的/*)
请记住,a
级别的其他元素也可以具有相同的属性
行为(移动到附加下)
此样式表:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="root[additional|someValue]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<additional>
<xsl:apply-templates select="additional/*|someValue"/>
</additional>
<xsl:apply-templates select="node()[not(self::additional|self::someValue)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
通过此输入:
<root>
<additional>
<b>something</b>
</additional>
<someValue>123</someValue>
<anotherValue>keep</anotherValue>
</root>
某物
123
保持
输出:
<root>
<additional>
<b>something</b>
<someValue>123</someValue>
</additional>
<anotherValue>keep</anotherValue>
</root>
某物
123
保持
请注意:只需一条规则即可覆盖标识转换。仅处理满足条件的root
(someValue
或additional
child)。复制root
,将模板应用于属性(以进一步处理),用附加的元素包装将模板应用于附加的子对象和root
的someValue
子对象的结果。最后,将模板应用于root
的子级,这些子级不是附加的也不是someValue
用于版本xslt 2.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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root">
<xsl:copy>
<additional>
<xsl:apply-templates/>
</additional>
</xsl:copy>
</xsl:template>
<xsl:template match="additional">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node() except someValue"/>
</xsl:copy>
</xsl:template>
<xsl:template match="additional">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:copy-of select="following-sibling::someValue"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
会尝试,但乍一看,它会在根下增加一倍吗?不会。为什么会这样?谢谢你,虽然不完全想要结果,但非常接近它,你给了我很多东西要思考和理解。结果与你问题中显示的结果有什么不同?如果我复制正确,已经在源中的节点(如果我们从一开始就已经有了其他节点)转到根。但是别担心,我已经想到了。如果你要显式复制所有内容,那么你就不需要身份转换模板。但这不符合您处理可能存在的其他元素的请求。我可能不理解某些内容,但我在根目录下有更多不相关的内容,它也应该被复制,所以身份转换不是用于此目的吗?但我显然忘记了在关闭root的模板之前调用。还是以前?是的,按照您现在的方式,身份转换模板将永远不会应用。如果您使用它,为什么不使用它而不是xsl:copy of
?这样,你最终会得到我在回答中所做的。谢谢,我喜欢它,背后的想法非常相似,但非常简洁。这并不能提供第一种情况下的预期结果: