Skip to content

Commit 2067eec

Browse files
committed
fix(xml): reject malformed else-if instead of silently dropping
1 parent bb2f9f0 commit 2067eec

2 files changed

Lines changed: 67 additions & 3 deletions

File tree

src/FlexRender.Xml/XmlToYamlNodeConverter.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,14 @@ private static void AddWrapper(YamlMappingNode node, string parentType, XElement
202202
node.Add(name, ConvertElementSequence(wrapper));
203203
break;
204204
case "else-if":
205-
var inner = wrapper.Elements().FirstOrDefault();
206-
if (inner is not null)
205+
var children = wrapper.Elements().ToList();
206+
if (children.Count != 1
207+
|| !string.Equals(children[0].Name.LocalName, "if", StringComparison.Ordinal))
207208
{
208-
node.Add("elseIf", ConvertElement(inner));
209+
throw new TemplateParseException(
210+
"An <else-if> must contain exactly one <if> child element.");
209211
}
212+
node.Add("elseIf", ConvertElement(children[0]));
210213
break;
211214
case "columns":
212215
node.Add("columns", ConvertAttributeItemSequence(wrapper));

tests/FlexRender.Tests/Parsing/Xml/XmlControlFlowTests.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using FlexRender.Parsing;
12
using FlexRender.Parsing.Ast;
23
using FlexRender.Xml;
34
using Xunit;
@@ -78,4 +79,64 @@ public void Parse_If_ElseIf()
7879
Assert.NotNull(ifEl.ElseIf);
7980
Assert.Equal("warm", ifEl.ElseIf!.CompareValue);
8081
}
82+
83+
[Fact]
84+
public void Parse_ElseIf_WithNoChild_Throws()
85+
{
86+
const string xml = """
87+
<flexrender>
88+
<canvas width="300"/>
89+
<if condition="status" equals="hot">
90+
<then><text content="HOT"/></then>
91+
<else-if></else-if>
92+
</if>
93+
</flexrender>
94+
""";
95+
96+
var ex = Assert.Throws<TemplateParseException>(() => _parser.Parse(xml));
97+
Assert.Contains("else-if", ex.Message);
98+
}
99+
100+
[Fact]
101+
public void Parse_ElseIf_WithNonIfChild_Throws()
102+
{
103+
const string xml = """
104+
<flexrender>
105+
<canvas width="300"/>
106+
<if condition="status" equals="hot">
107+
<then><text content="HOT"/></then>
108+
<else-if>
109+
<text content="oops"/>
110+
</else-if>
111+
</if>
112+
</flexrender>
113+
""";
114+
115+
var ex = Assert.Throws<TemplateParseException>(() => _parser.Parse(xml));
116+
Assert.Contains("else-if", ex.Message);
117+
}
118+
119+
[Fact]
120+
public void Parse_ElseIf_WithMultipleChildren_Throws()
121+
{
122+
const string xml = """
123+
<flexrender>
124+
<canvas width="300"/>
125+
<if condition="status" equals="hot">
126+
<then><text content="HOT"/></then>
127+
<else-if>
128+
<if condition="status" equals="warm">
129+
<then><text content="WARM"/></then>
130+
</if>
131+
<if condition="status" equals="cool">
132+
<then><text content="COOL"/></then>
133+
</if>
134+
</else-if>
135+
</if>
136+
</flexrender>
137+
""";
138+
139+
var ex = Assert.Throws<TemplateParseException>(() => _parser.Parse(xml));
140+
Assert.Contains("else-if", ex.Message);
141+
}
81142
}

0 commit comments

Comments
 (0)