我是XSLT的新手,但是我为工作做了很多XML修改,所以我正在努力学习。我以下列格式输入XML(上面和下面有XML):
<Parent Value="x">
<!---->Unlimited number of child elements could exist with any value from 0-1
<Child Value="0.1"/>
<Child Value="1"/>
<Child Value="0.30"/>
...
</Parent>
我需要以下列格式的父/子节点输出XML :
<Parent Value="x">
<Child Value="0.3"/>
</Parent>
只有一个子元素且其值恒定为0.3。
我的当前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">
<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="@*|*"/>
<Child Value="0.3"/>
</Parent>
</xsl:template>
<xsl:template match="Child[@Value!=0.3]"/>
我试图在所有文件中创建所需的子元素(如果它不存在的话)
<Child Value="0.3"/>
然后仅在其值= 0.3时输出子元素。但是,这有时会导致子节点的重复,我觉得我可能不会以正确的方式接近它。此外,xmlns:xs标题出现在Parent元素之后,而不是在输出文档的顶部。任何指导将不胜感激!
当前输出示例:
<Parent Value="x" 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">
<Child Value="0.30" />
<Child Value="0.3" />
</Parent>
答案 0 :(得分:2)
只有两件事需要修改:
1 在此处使用单引号:
<xsl:template match="Child[@Value!='0.3']"/>
如果您没有,则该值将被解释为数字,否则将被解释为字符串。为什么这很重要?因为如果表达式的右侧是数字,则属性值也会转换为数字 - 而0.3
和0.30
最终会相同。最终导致输出多个Child
元素。
2 使用Child
有意插入xsl:if
元素。显而易见,取决于此特定元素是否已存在于输入中。然后,您不会在输出中获得两个Child
元素。
注意:Parent
中不是属性或元素节点(即processing-instruction()
和comment()
)的任何子节点都会在样式表中被忽略。这是因为您只将模板应用于@*|*
,而不是@*|node()
。
<强>样式表强>
<?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">
<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="@*|*"/>
<xsl:if test="not(Child[@Value = '0.3'])">
<Child Value="0.3"/>
</xsl:if>
</Parent>
</xsl:template>
<xsl:template match="Child[@Value!='0.3']"/>
</xsl:stylesheet>
XML输入
<?xml version="1.0" encoding="UTF-8"?>
<Parent Value="x">
<Child Value="0.30"/>
<Child Value="1"/>
<Child Value="0.4"/>
<Child Value="0.3">The right one</Child>
</Parent>
XML输出
<Parent 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"
Value="x">
<Child Value="0.3">The right one</Child>
</Parent>
目前,输出XML中有未使用的命名空间。您可以通过将exclude-result-prefixes="#all"
添加到xsl:stylesheet
来阻止它们出现在输出中。如果这样做,那么输出将简化为
<Parent Value="x">
<Child Value="0.3">The right one</Child>
</Parent>
答案 1 :(得分: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" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Child"/>
<xsl:template match="Parent">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<Child Value="0.3"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>