基本上,这是我正在尝试的逻辑。
对于父节点(ByFirstNameSearchList或ByLastNameSearchList):
-All子元素值为空(value1-4),插入值为% - 当一个或任何子元素具有值时,使用NOVAL替换所有具有空值的兄弟。
我有以下XML:
<GetName>
<ByLastNameSearchList>
<Value1/>
<Value2/>
<Value3/>
<Value4/>
<Value5/>
</ByLastNameSearchList>
<ByFirstNameSearchList>
<Value1>String</Value1>
<Value2>String</Value2>
<Value3/>
<Value4/>
<Value5/>
</ByFirstNameSearchList>
</GetName>
这就是我想要的样子:
<GetName>
<ByLastNameSearchList>
<Value1>%</Value1>
<Value2>%</Value2>
<Value3>%</Value3>
<Value4>%</Value4>
<Value5>%</Value5>
</ByLastNameSearchList>
<ByFirstNameSearchList>
<Value1>String</Value1>
<Value2>String</Value2>
<Value3>NOVAL</Value3>
<Value4>NOVAL</Value4>
<Value5>NOVAL</Value5>
</ByFirstNameSearchList>
</GetName>
我真的很感谢你帮助我。相信我,我用我有限的XSL知识尝试了一切。
感谢。
答案 0 :(得分:0)
此样式表
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.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="*|@*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="ByFirstNameSearchList/* | ByLastNameSearchList/*">
<xsl:copy>
<xsl:choose>
<xsl:when test="string-length(text()) gt 0">
<xsl:value-of select="text()"/>
</xsl:when>
<xsl:when test="some $Value in ../* satisfies string-length($Value/text()) gt 0">
<xsl:text>NOVAL</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>%</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
将产生您想要的输出。
更新:
这个版本更通用,因为它不依赖于只包含字符串的非空元素:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.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="*|@*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="ByFirstNameSearchList/* | ByLastNameSearchList/*">
<xsl:choose>
<xsl:when test="string-length(text()) gt 0">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:when test="some $Value in ../* satisfies string-length($Value/text()) gt 0">
<xsl:copy>
<xsl:text>NOVAL</xsl:text>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:text>%</xsl:text>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
就像这个一样简单(适用于XSLT 2.0和XSLT 1.0):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*/*[not(node())]">
<xsl:copy>NOVAL</xsl:copy>
</xsl:template>
<xsl:template match="/*/*[not(*/node())]/*">
<xsl:copy>%</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<GetName>
<ByLastNameSearchList>
<Value1/>
<Value2/>
<Value3/>
<Value4/>
<Value5/>
</ByLastNameSearchList>
<ByFirstNameSearchList>
<Value1>String</Value1>
<Value2>String</Value2>
<Value3/>
<Value4/>
<Value5/>
</ByFirstNameSearchList>
</GetName>
产生了想要的正确结果:
<GetName>
<ByLastNameSearchList>
<Value1>%</Value1>
<Value2>%</Value2>
<Value3>%</Value3>
<Value4>%</Value4>
<Value5>%</Value5>
</ByLastNameSearchList>
<ByFirstNameSearchList>
<Value1>String</Value1>
<Value2>String</Value2>
<Value3>NOVAL</Value3>
<Value4>NOVAL</Value4>
<Value5>NOVAL</Value5>
</ByFirstNameSearchList>
</GetName>
<强>解释强>:
身份规则“按原样”复制为其选择执行的每个节点。
模板会覆盖任何元素的标识模板,该元素是top元素的子元素,并且没有子元素。这将复制元素并生成一个文本节点子节点,其字符串值为字符串“NOVAL”。
第二个覆盖模板,它覆盖身份模板和第一个覆盖模板:匹配任何元素,该元素是top元素的子元素,其父元素没有包含子节点的子元素。这将复制元素并生成一个文本节点子节点,其字符串值为字符串“%”。
请注意:
这是一种纯粹的“推动式”转型。
没有明确的条件说明(没有xsl:choose
,没有xsl:when
,没有xsl:otherwise
),没有xsl:text
甚至没有xsl:apply-templates
(除了在身份模板中)。
没有使用特殊的XPath 2.0表达式(some ... satisfies ...
),因为它们是不必要的。
未使用string-length()
功能。