使用XSLT 1.0:
我将以下xml作为输入
<?xml version="1.0" encoding="utf-8" ?>
<Root>
<Sub1>
<Val1>A</Val1>
<Val3>C</Val3>
</Sub1>
<Sub2>
<Val2>NIL</Val2>
<Val4>D</Val4>
</Sub2>
</Root>
和我的XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/Root">
<xsl:element name ="New">
<xsl:apply-templates select="Sub1"/>
<xsl:apply-templates select="Sub2"/>
</xsl:element>
</xsl:template>
<xsl:template match="Sub1" >
<xsl:variable name='pr' select='.'/>
<xsl:element name="Myelement1" >
<!-- The value should be added to the output regardless-->
<xsl:value-of select="$pr/Val1"/>
<xsl:if test="number($pr/Val1) = $pr/Val1">
<!--TWO things should be done:
1- Check if <messages> is created in the output XML? if not it should be created
2- A message Should be added to <Messages> like <Message> Myelement1 is not numeric </Message>-->
</xsl:if>
</xsl:element>
</xsl:template>
<xsl:template match="Sub2" >
<xsl:variable name='pr' select='.'/>
<xsl:element name="Myelement2" >
<!-- The value should be added to the output regardless-->
<xsl:value-of select="$pr/Val2"/>
<xsl:if test="$pr/Val2='NIL'">
<!--TWO things should be done:
1- Check if <messages> is created in the output XML? if not it should be created
2- A message Should be added to <Messages> like <Message> Myelement2 is not valid </Message>-->
</xsl:if>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
当前的XSLT生成以下输出:
<?xml version="1.0" encoding="utf-8"?>
<New>
<Myelement1>A</Myelement1>
<Myelement2>NIL</Myelement2>
</New>
但这是我真正想要的:
<?xml version="1.0" encoding="utf-8"?>
<New>
<Myelement1>A</Myelement1>
<Myelement2>NIL</Myelement2>
<Messages>
<Message> Myelement1 is not numeric </Message>
<Message> Myelement2 is not valid </Message>
</Messages>
</New>
我的问题是Messages元素。
此元素是动态的,消息子元素的数量可以变化,并且取决于源XML的内容。
它也可能是空的,但是最大的问题是我想在运行时添加这些消息子元素,而XSLT正在使用多个模板等在源xml文件中进行导航。
所以说,我有两个不同的模板来生成名为Temp1和temp2的Myelement1和Myelement2,因此我想在messages元素下添加一些消息(不是常量消息,可以是任何东西),而所应用的模板(temp1)是正在执行,然后在执行第二个模板(temp2)时再发送一些不同的消息(不是常量消息)。
例如 如果A不是数字,则应该是如下消息:
<message> myelement1 is not in a correct format < Message>
将message元素视为日志或错误元素。
感谢您的帮助。
答案 0 :(得分:1)
您可以分两次通过。在第一遍中,您可以将结果存储在一个变量中,在创建或更改任何新元素之后,只需创建Message
元素。
然后在第二遍中,您可以简单地更改任何存在的Message
元素的位置,尽管在XSLT 1.0中,您将必须使用node-set
扩展功能来完成此操作,因为您创建的用于保存第一遍的变量将是“结果树片段”。广泛支持exslt节点集功能,因此您应该可以使用它。
尝试使用此XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/Root">
<xsl:variable name="pass1">
<xsl:element name ="New">
<xsl:apply-templates select="Sub1"/>
<xsl:apply-templates select="Sub2"/>
</xsl:element>
</xsl:variable>
<xsl:apply-templates select="exslt:node-set($pass1)" xmlns:exslt="http://exslt.org/common" mode="pass2" />
</xsl:template>
<xsl:template match="Sub1" >
<xsl:variable name='pr' select='.'/>
<xsl:element name="Myelement1" >
<xsl:value-of select="$pr/Val1"/>
</xsl:element>
<xsl:if test="not(number($pr/Val1) = $pr/Val1)">
<Message>Myelement1 is not numeric</Message>
</xsl:if>
</xsl:template>
<xsl:template match="Sub2" >
<xsl:variable name='pr' select='.'/>
<xsl:element name="Myelement2" >
<xsl:value-of select="$pr/Val2"/>
</xsl:element>
<xsl:if test="$pr/Val2='NIL'">
<Message>Myelement2 is not valid</Message>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()" mode="pass2">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="New[Message]" mode="pass2">
<xsl:copy>
<xsl:apply-templates select="node()[not(self::Message)]" mode="pass2" />
<Messages>
<xsl:apply-templates select="Message" mode="pass2" />
</Messages>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
另一种方法是对输出的每个部分使用单独的模板。考虑下面的简化示例:
XML
<root>
<elemA>alpha</elemA>
<elemB>55</elemB>
</root>
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="/root">
<output>
<xsl:apply-templates select="elemA | elemB"/>
<Messages>
<xsl:apply-templates select="elemA | elemB" mode="messages"/>
</Messages>
</output>
</xsl:template>
<xsl:template match="elemA">
<Myelement1>
<xsl:value-of select="." />
</Myelement1>
</xsl:template>
<xsl:template match="elemB">
<Myelement2>
<xsl:value-of select="." />
</Myelement2>
</xsl:template>
<xsl:template match="elemA" mode="messages">
<xsl:if test="not(number(.)=number(.))">
<Message>Myelement1 is not a number.</Message>
</xsl:if>
</xsl:template>
<xsl:template match="elemB" mode="messages">
<xsl:if test=". > 50">
<Message>Myelement2 is greater than 50.</Message>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
结果
<?xml version="1.0" encoding="UTF-8"?>
<output>
<Myelement1>alpha</Myelement1>
<Myelement2>55</Myelement2>
<Messages>
<Message>Myelement1 is not a number.</Message>
<Message>Myelement2 is greater than 50.</Message>
</Messages>
</output>