如何获取 Xml 节点的全名
How do I get the full name of the Xml Node
我有一个示例 xml 文件,看起来像这样。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBlock Text="First Text" Margin="5"/>
<Label Content="Second Text" HorizontalAlignment="Center"/>
<TextBox Text="Third Text"/>
<GroupBox Header="Fourth Text">
Fifth Text
that extends to another line.
</GroupBox>
<Button Content="Sixth Text"/>
<Frame Content="<Seventh Text>"></Frame>
<ComboBox>
Eighth Text</ComboBox>
<Label Content="{Binding LabelText}" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
我的输出文件如下所示:
(4)Title="MainWindow"
(7)Text="First Text"
(8)Content="Second Text"
(9)Text="Third Text"
(10)Header="Fourth Text"
(11) Fifth Text that extends to another line.
(14)Content="Sixth Text"
(15)Content="<Seventh Text>"
(17) Eighth Text
这主要是我想要的。但是,出于某种原因,我只得到 "Title" 和 "Text" 以及 "Content" 等等。但我希望它打印出 "TextBlock Text" 和 "Label Content" 以及 "TextBox Text" 和 "Button Content" 等等。我正在使用 XmlTextReader,但我似乎无法找到任何支持来打印它。 reader.Name 只是打印出我已有的内容。
这是我的代码:
public void ParseXml(String filename)
{
XmlTextReader reader = new XmlTextReader(filename);
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
for (int i = 0; i < reader.AttributeCount; i++)
{
reader.MoveToAttribute(i);
if (reader.LineNumber < 4)
{
continue;
}
//WriteLine(Path.GetFullPath(filename));
if(reader.Name != "Width" && reader.Name != "Height" && reader.Name != "Margin"
&& reader.Name != "HorizontalAlignment")
WriteLine("(" + reader.LineNumber + ")" + reader.ReadOuterXml());
}
break;
case XmlNodeType.Text:
WriteLine("(" + (reader.LineNumber + 1) + ") " + reader.Value.Replace("\r\n","").Trim());
break;
case XmlNodeType.EndElement:
break;
}
}
reader.Close();
}
谢谢!
正如我在评论中暗示的那样,您需要在 reader 仍在元素上时获得 reader.Name
的结果 - before 你移动通过调用 reader.MoveToAttribute(i)
.
除非您有特殊原因(例如性能或非常大的文件),否则使用更高级别 API 会容易得多,例如 LINQ to XML.
一个简单的实现可能如下所示:
var document = XDocument.Load(filename, LoadOptions.SetLineInfo);
var excludedAttributes = new HashSet<XName>
{
"{http://schemas.microsoft.com/winfx/2006/xaml}Class",
"Width",
"Height",
"Margin",
"HorizontalAlignment"
};
foreach (var element in document.Descendants())
{
IXmlLineInfo lineInfo = element;
var sb = new StringBuilder();
sb.AppendFormat("({0}) ", lineInfo.LineNumber);
sb.Append(element.Name.LocalName);
var outputAttributes = element.Attributes()
.Where(a => !a.IsNamespaceDeclaration && !excludedAttributes.Contains(a.Name));
foreach (var attribute in outputAttributes)
{
sb.AppendFormat(" {0}=\"{1}\"", attribute.Name, attribute.Value);
}
if (element.Nodes().OfType<XText>().Any())
{
sb.Append(" ");
sb.Append(element.Value.Replace("\n", string.Empty).Trim());
}
WriteLine(sb.ToString());
}
我有一个示例 xml 文件,看起来像这样。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBlock Text="First Text" Margin="5"/>
<Label Content="Second Text" HorizontalAlignment="Center"/>
<TextBox Text="Third Text"/>
<GroupBox Header="Fourth Text">
Fifth Text
that extends to another line.
</GroupBox>
<Button Content="Sixth Text"/>
<Frame Content="<Seventh Text>"></Frame>
<ComboBox>
Eighth Text</ComboBox>
<Label Content="{Binding LabelText}" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
我的输出文件如下所示:
(4)Title="MainWindow"
(7)Text="First Text"
(8)Content="Second Text"
(9)Text="Third Text"
(10)Header="Fourth Text"
(11) Fifth Text that extends to another line.
(14)Content="Sixth Text"
(15)Content="<Seventh Text>"
(17) Eighth Text
这主要是我想要的。但是,出于某种原因,我只得到 "Title" 和 "Text" 以及 "Content" 等等。但我希望它打印出 "TextBlock Text" 和 "Label Content" 以及 "TextBox Text" 和 "Button Content" 等等。我正在使用 XmlTextReader,但我似乎无法找到任何支持来打印它。 reader.Name 只是打印出我已有的内容。
这是我的代码:
public void ParseXml(String filename)
{
XmlTextReader reader = new XmlTextReader(filename);
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
for (int i = 0; i < reader.AttributeCount; i++)
{
reader.MoveToAttribute(i);
if (reader.LineNumber < 4)
{
continue;
}
//WriteLine(Path.GetFullPath(filename));
if(reader.Name != "Width" && reader.Name != "Height" && reader.Name != "Margin"
&& reader.Name != "HorizontalAlignment")
WriteLine("(" + reader.LineNumber + ")" + reader.ReadOuterXml());
}
break;
case XmlNodeType.Text:
WriteLine("(" + (reader.LineNumber + 1) + ") " + reader.Value.Replace("\r\n","").Trim());
break;
case XmlNodeType.EndElement:
break;
}
}
reader.Close();
}
谢谢!
正如我在评论中暗示的那样,您需要在 reader 仍在元素上时获得 reader.Name
的结果 - before 你移动通过调用 reader.MoveToAttribute(i)
.
除非您有特殊原因(例如性能或非常大的文件),否则使用更高级别 API 会容易得多,例如 LINQ to XML.
一个简单的实现可能如下所示:
var document = XDocument.Load(filename, LoadOptions.SetLineInfo);
var excludedAttributes = new HashSet<XName>
{
"{http://schemas.microsoft.com/winfx/2006/xaml}Class",
"Width",
"Height",
"Margin",
"HorizontalAlignment"
};
foreach (var element in document.Descendants())
{
IXmlLineInfo lineInfo = element;
var sb = new StringBuilder();
sb.AppendFormat("({0}) ", lineInfo.LineNumber);
sb.Append(element.Name.LocalName);
var outputAttributes = element.Attributes()
.Where(a => !a.IsNamespaceDeclaration && !excludedAttributes.Contains(a.Name));
foreach (var attribute in outputAttributes)
{
sb.AppendFormat(" {0}=\"{1}\"", attribute.Name, attribute.Value);
}
if (element.Nodes().OfType<XText>().Any())
{
sb.Append(" ");
sb.Append(element.Value.Replace("\n", string.Empty).Trim());
}
WriteLine(sb.ToString());
}