当使用XSLT将某个条件满足到xml文档时,我无法插入文本块。假设我有以下xml:
<oldStep Name="Step1">
<oldItems>
<oldItem ItemName="item1">
</oldItem>
<!-- want to add an extra <Item> here if Step Name == "Step1" -->
<oldItem ItemName="Step1item">
</oldItem>
</oldItems>
</oldStep>
<oldStep Name="Step2">
<oldItems>
...
</oldItems>
</oldStep>
在旧节点名称转换为新节点名称的过程中,每当oldStep Name等于某个值(在本例中为Step1)时,我想添加一个额外的文本块(或手动构造的节点)。我尝试使用下面的XSLT,但最后有一个奇怪的行为,即在匹配时将文本块添加到xml中的每个节点(有时甚至不在节点下)。另外,我在跳过节点时遇到问题,因此可以在Items中插入节点,而不是直接在oldStep下插入:
<xsl:template match="oldItems">
<xsl:element name="Item">
<xsl:if test="../@Name = 'Step1'>
<xsl:call-template name = "identity"></xsl:call-template>
</xsl:if>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="node()" name="identity">
<xsl:element name="Item">
<xsl:attribute name="ItemName">Step1item</xsl:attribute>
</xsl:apply-templates />
</xsl:element>
</xsl:template>
我觉得我的条件不对,但谷歌搜索没有真正的帮助(搜索字符串太模糊)。我在xsl中缺少什么?或者,有没有更好的方法解决这个问题?
感谢。
答案 0 :(得分:1)
此转化:
<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()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="oldStep[@Name='Step1']/*/oldItem[1]">
<xsl:call-template name="identity"/>
<Item ItemName='Step1item'/>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<steps>
<oldStep Name="Step1">
<oldItems>
<oldItem ItemName="item1"/>
<!-- want to add an extra <Item> here if Step Name == "Step1" -->
<oldItem ItemName="Step1item"/>
</oldItems>
</oldStep>
<oldStep Name="Step2">
<oldItems>
...
</oldItems>
</oldStep>
</steps>
产生想要的结果:
<steps>
<oldStep Name="Step1">
<oldItems>
<oldItem ItemName="item1"/>
<Item ItemName="Step1item"/><!-- want to add an extra <Item> here if Step Name == "Step1" -->
<oldItem ItemName="Step1item"/>
</oldItems>
</oldStep>
<oldStep Name="Step2">
<oldItems>
...
</oldItems>
</oldStep>
</steps>
答案 1 :(得分:1)
名为“identity”的模板与任何节点匹配,因此会将其应用于它处理的每个节点。不要把它与任何东西相匹配。
答案 2 :(得分:1)
您的描述有点难以理解。以下是我解释您的问题的方法:
给我一个默认复制一切的变压器,除了:
- 它将oldItem元素转换为Item元素
- 它在“步骤1”下的oldItems元素中添加了一个额外的项目,作为最后一个元素
这是一个解决方案:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- by default, copy everything -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- special handling for old items -->
<xsl:template match="oldItems">
<!-- transform all old items first -->
<xsl:apply-templates select="@*|node()"/>
<xsl:if test="../@Name = 'Step1'">
<xsl:call-template name="add-new-step1-stuff"/>
</xsl:if>
</xsl:template>
<!-- add new step 1 stuff -->
<xsl:template name="add-new-step1-stuff">
<xsl:element name="Item">
<xsl:attribute name="ItemName">Step1item</xsl:attribute>
</xsl:element>
</xsl:template>
<!-- converts each oldItem to Item -->
<xsl:template match="oldItem">
<xsl:element name="Item">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
,当应用于:
<?xml version="1.0" encoding="utf-8"?>
<oldSteps>
<oldStep Name="Step1">
<oldItems>
<oldItem ItemName="item1"></oldItem>
</oldItems>
</oldStep>
<oldStep Name="Step2">
<oldItems>
<oldItem ItemName="item2"></oldItem>
<oldItem ItemName="item3"></oldItem>
</oldItems>
</oldStep>
</oldSteps>
(不完全是你给的,但我认为你的意思)
的产率:
<?xml version="1.0"?>
<oldSteps>
<oldStep Name="Step1">
<Item ItemName="item1"/>
<Item ItemName="Step1item"/>
</oldStep>
<oldStep Name="Step2">
<Item ItemName="item2"/>
<Item ItemName="item3"/>
</oldStep>
</oldSteps>
需要一些空白清理,但我认为是你正在寻找的结构。
如果你想要块文本而不是额外的项目,你只需要像这样重写add-new-step1-stuff
模板:
<!-- add new step 1 stuff -->
<xsl:template name="add-new-step1-stuff">
<xsl:text>
Here's some block text that goes at the end.
</xsl:text>
</xsl:template>
我的样式表和你的样式表之间的主要区别: