Как получить все XML-узлы с одинаковым именем, не зная их уровня?
у меня есть пример XML:
<Fruits>
<Red_fruits>
<Red_fruits></Red_fruits>
</Red_fruits>
<Yellow_fruits>
<banana></banana>
</Yellow_fruits>
<Red_fruits>
<Red_fruits></Red_fruits>
</Red_fruits>
</Fruits>
у меня есть 4 тега Red_fruits, 2 из них имеют один и тот же ParentNode (фрукты), я хочу получить те, которые имеют один и тот же ParentNode.
но я просто хочу те, которые имеют то же имя (Red_fruits), что означает, что тег Yellow_fruits не включен.
это то, как я делаю прямо сейчас, используя язык C#:
XmlDocument doc = new XmlDocument();
string selectedTag = cmbX.text;
if (File.Exists(txtFile.text))
{
try
{
//Load
doc.Load(cmbFile.text);
//Select Nodes
XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag);
}
Catch
{
MessageBox.show("Some error message here");
}
}
Это возвращает мне все red_fruits, а не только те, которые принадлежат Фрукты.
Я не могу сделать XmlNodeList = doc.SelectNodes ("/Fruits/Red_fruits"), потому что я хочу использовать этот код для чтения случайных XML-файлов, поэтому я не знаю точного имени, которое будет иметь конкретный узел, мне просто нужно поместить все узлы с тем же именем и тем же уровнем в XmlNodeList использование языка C#.
есть ли способ достичь этого без использования LINQ? Как это сделать?
3 ответов
Если вы просто пытаетесь найти" следующую "или" предыдущую " итерацию одного узла, вы можете сделать следующее, а затем сравнить его с именем
XmlNode current = doc.SelectSingleNode("Fruits").SelectSingleNode("Red_fruits");
XmlNode previous = current.NextSibling;
XmlNode next = current.NextSibling;
и вы можете повторять, пока не найдете подходящего брата
while(next.Name != current.Name)
{
next = next.NextSibling;
}
или вы даже можете получить свой список, вызвав свойство "Parent"
XmlNodeList list = current.ParentNode.SelectNodes(current.Name);
понимание использования одной косой черты /
и двойной Слэш //
могу помочь здесь.
давайте посмотрим, как /
и //
работы по отношению к корневому узлу. Когда /
используется в начале пути:
/a
он определит абсолютный путь к узлу a
относительно корня. Таким образом, в этом случае он найдет только a
узлы в корне дерева XML.
, когда //
используется в начале путь:
//a
он определит путь к узлу a
в любом месте XML-документа. Таким образом, в этом случае, он найдет a
узлы, расположенные на любой глубине в дереве XML.
эти выражения XPath также могут использоваться в середине значения XPath для определения отношений предок-потомок. Когда /
используется в середине пути:
/a/b
он определит путь к узлу b
это непосредственный прямой потомок (т. дочерний) узла a
.
, когда //
используется в середине пути:
/a//b
он определит путь к узлу b
что это любой потомок узла a
.
возвращаясь к вашему вопросу:
// С помощью GetElementsByTagName()
верните все элементы, имеющие имя: Red_Fruits
XmlDocument doc = new XmlDocument();
XmlNodeList nodes= doc.GetElementsByTagName("Red_Fruits");
//С помощью SelectNodes()
метод
XmlNodelist nodes = doc.SelectNodes("//Fruits/Red_Fruits");
/ / это будет выбрать все элементы, которые являются дочерними <Fruits>
элемент.
в случае <Fruits>
корневой элемент использует Xpath:/Fruits/Red_Fruits
. [ одинарного слеша /
]
в худшем случае можно выполнить цикл элементов XMLNode в selectedNodeList и проверить свойства ParentNode. При необходимости вы можете пойти рекурсивно на проверку ParentNode и подсчитать количество раз, необходимое, чтобы добраться до корневого узла. Это даст вам глубину узла. Или вы можете сравнить ParentNode на каждом уровне, чтобы увидеть, является ли он родителем, который вас интересует, если этот родитель не является корнем.
public void Test(){
XmlDocument doc = new XmlDocument();
string selectedTag = cmbX.text;
if (File.Exists(txtFile.text))
{
try
{
//Load
doc.Load(cmbFile.text);
//Select Nodes
XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag);
List<XmlNode> result = new List<XmlNode>();
foreach(XmlNode node in selectedNodeList){
if(depth(node) == 2){
result.Add(node);
}
}
// result now has all the selected tags of depth 2
}
Catch
{
MessageBox.show("Some error message here");
}
}
}
private int depth(XmlNode node) {
int depth = 0;
XmlNode parent = node.ParentNode;
while(parent != null){
parent = node.ParentNode;
depth++;
}
return depth;
}