开发者

c# .net xpath not picking out elements when traversing

I am working on a page that uses XPATH to traverse an XML document to pull certain data elements and build a string based on them. I am able to count the elements correctly, but when trying to order traverse through them some of the elements that are being counted are not showing up. Most likely the task could be accomplished more efficiently, any assistance on accomplishing this task correctly would be appreciated.

XML

<?xml version="1.0" encoding="UTF-16"?>
<Presentation>
    <Filename>Name of file</Filename>
    <version>1.2</version>
    <threshold>23</threshold> <!-- gives number of slides -->
    <Slides>
        <Slide id="slide id">
            <Filename>Name of file</Filename>
            <Title>Title of slide</Title>
        </Slide>
        <Slide id="slide id">
            <Filename>Name of file</Filename>
            <Title>Title of slide</Title>
            <quizobjects>
                <quizobject id="1">
                <filename>Name of quiz</filename>
            </quizobjects>
        </Slide>
        <Slide id="slide id">
            <Filename>Name of file</Filename>
            <Title>Title of slide</Title>
        </Slide>
        ...etc
     </Slides>
</Presentation>

Here is an example of the XML. I traverse through the slides counting them, as well as counting the quizobjects. (This returns correct numbers) However when I traverse through all slides trying to get the location of each quiz in the Slides node, it never hits any quizobjects.

C#

int numSlides;

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlToParse.Text); //pass in xml string
XmlElement root = doc.DocumentElement;

//get number of slides from threshold node
numSlides = Convert.ToInt32(root.SelectSingleNode("//threshold").InnerText);

//get number of开发者_如何学C quizzes/slides
XmlNodeList xnQuiz = root.SelectNodes("/Presentation/Slides/Slide/quizobjects"); //returns 7
XmlNodeList xnList = root.SelectNodes("/Presentation/Slides/Slide");

int[] quizLocArray = new int[xnQuiz.Count]; //create array to hold location of quizzes

int j = 0;
//find index of quizzes in slide list
for(int i = 0; i < xnList.Count; i++)
{
    XmlNode quiz = xnList[i].SelectSingleNode("/quizobjects");
    if(quiz != null) //stepping through quiz always equals null
    {
        quizLocArray[j] = (i + 1);
        j++;
    }
}

Output

numSlides/Total Number of Slides in XML: 23

xnQuiz.Count/Total Number of Quizzes in XML: 7

String.Join(",", quizLocArray)/Array of indexes of quizzes in slide list: 0,0,0,0,0,0,0


It appears as if your XML data is not properly formatted, as you are missing a closing </quizobject>. I am going to go ahead and assume this is just a typo.

You need to change your XPath query from SelectSingleNode("/quizobjects") to SelectSingleNode("quizobjects") to get the XML element you want.

Presentation.xml file:

<Presentation>
  <Filename>Name of file</Filename>
  <version>1.2</version>
  <threshold>23</threshold>

  <!-- gives number of slides -->
  <Slides>
    <Slide id="slide id">
      <Filename>Name of file</Filename>
      <Title>Title of slide</Title>
    </Slide>
    <Slide id="slide id">
      <Filename>Name of file</Filename>
      <Title>Title of slide</Title>
      <quizobjects>
        <quizobject id="1">
          <filename>Name of quiz</filename>
        </quizobject>
      </quizobjects>
    </Slide>
    <Slide id="slide id">
      <Filename>Name of file</Filename>
      <Title>Title of slide</Title>
    </Slide>
  </Slides>

</Presentation>

C# Code:

XmlDocument doc     = new XmlDocument();

try
{
    using (var reader = XmlReader.Create("Presentation.xml"))
    {
        int numSlides;

        doc.Load(reader);

        XmlElement root = doc.DocumentElement;

        //get number of slides from threshold node
        numSlides = Convert.ToInt32(root.SelectSingleNode("//threshold").InnerText);

        //get number of quizzes/slides
        XmlNodeList xnQuiz = root.SelectNodes("/Presentation/Slides/Slide/quizobjects");
        XmlNodeList xnList = root.SelectNodes("/Presentation/Slides/Slide");

        //create array to hold location of quizzes
        int[] quizLocArray = new int[xnQuiz.Count];

        int j = 0;

        //find index of quizzes in slide list
        for (int i = 0; i < xnList.Count; i++)
        {
            XmlNode quiz = xnList[i].SelectSingleNode("quizobjects");
            if (quiz != null)
            {
                quizLocArray[j] = (i + 1);
                j++;
            }
        }
    }
}
catch (Exception exception)
{
    Console.WriteLine(exception.Message);
}


Two problems:

  • In your example XML, /Presentation/Slides/Slide[id='slide id']/quizobjects/quizobject does not have an ending tag (and is not itself an empty tag)
  • Your last XPath for quizobjects has an extra /. Change it to "quizobjects" and it will work

Changed code:

for(int i = 0; i < xnList.Count; i++)
{
    XmlNode quiz = xnList[i].SelectSingleNode("quizobjects"); // Changed from "/quizobjects"
    if(quiz != null) //stepping through quiz always equals null
    {
        quizLocArray[j] = (i + 1);
        j++;
    }
}


Just replace '/quizobjects' with 'quizobjects' in the statement:

XmlNode quiz = xnList[i].SelectSingleNode("/quizobjects");

Hope, it'll work..

when the path starts with / it always consider it as absolute path. That's the reason you are not getting the element.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜