有人可以帮我创建LINQ to XML查询吗?

时间:2020-11-29 01:32:10

I've got three classes

我有三节课

ExamProduced:
+ ExamID
+ Date
+ Seed
+ Exercises

Exercise
+ Quantity
+ IsMakeUp
+ Score
+ Answers

Answer
+ IsCorrect

And I've got this Xml file

我有这个Xml文件

    <Answers ExamID="1" StudentID="abcd" Date="10/26/2011 11:50:34 AM" 
             Seed="495" IsSED="False">
      <Summary>
        <Objective ID="1" MakeUp="False" Quantify="5" 
                   Difficulty="Easy" Accredited="True" Produced="True">
          <Details Result="0" Date="10/26/2011 11:35:18 AM" />
          <Details Result="1" Date="10/26/2011 11:50:34 AM" />
        </Objective>
        <Objective ID="2" MakeUp="True" Quantify="5" 
                   Difficulty="Easy" Accredited="False" Produced="True">
          <Details Result="0" Date="10/26/2011 11:35:18 AM" />
          <Details Result="0" Date="10/26/2011 11:50:34 AM" />
        </Objective>
        <Objective ID="3" MakeUp="True" Quantify="2" 
                   Difficulty="Easy" Accredited="False" Produced="False">
          <Details Result="0" Date="10/26/2011 11:35:18 AM" />
          <Details Result="0" Date="10/26/2011 11:50:34 AM" />
        </Objective>
      </Summary>
      <Answer ProblemID="0" ObjectiveID="1" IsCorrect="True" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="9" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="1" IsCorrect="True" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="20" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="1" IsCorrect="True" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="16" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="1" IsCorrect="True" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="36" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="1" IsCorrect="True" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="18" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="2" IsCorrect="False" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="Null" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="2" IsCorrect="False" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="Null" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="2" IsCorrect="False" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="Null" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="2" IsCorrect="False" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="Null" />
      </Answer>
      <Answer ProblemID="0" ObjectiveID="2" IsCorrect="False" Difficulty="Easy">
        <Result DataType="System.Decimal" Value="Null" />
      </Answer>
    </Answers>

Well, I need a bit of help to create this query. ExamProduced properties can get through the root. Then in exercise, take a look at the tag Summary, in this place is an historial.. so, I need to get those values where the attribute Produced is true.

好吧,我需要一些帮助来创建这个查询。 ExamProduced属性可以通过root。然后在练习中,看看标签摘要,在这个地方是一个历史..所以,我需要获得属性Produced为true的那些值。

For example, two objectives where produced is true are the 1 and 2 objectivesId. Then I need to get the values quantity and make up (for exercise class). Then like 1 and 2 objective were produced, each one has answers I need to get if the value was correct o wrong.

例如,生成的两个目标是1和2个目标。然后我需要得到数量和弥补(对于练习课)。然后像1和2目标一样产生,每个人都有我需要得到的答案,如果值是正确的错误。

Thanks in advance.

提前致谢。

EDIT: For example at this case, the classes should have:

编辑:例如在这种情况下,类应该具有:

ExamProduced
+ ExamID: 1
+ Date: 10/26/2011 11:50:34 AM
+ Seed: 495
+ Exercises: { 2 items }
  {
      Exercise
      {
          + Quantity = 5
          + IsMakeUp = False;
          + Score = 1 (it means one hundred for Answers/Summary/Objective/LastDetail => Result)
          + Answers (5 items)
            {
               Answer
               {
                   + IsCorrect = true
               }
               Answer
               {
                   + Is...
               }
               Ans {..}
               Ans {..}
               Ans {..}
            }
      }
      Exercise
      {
          ...
      }
  }

2 个解决方案

#1


1  

Here's my slightly over-engineered solution for the data you're trying to build. To use it:

这是我为您正在尝试构建的数据略微过度设计的解决方案。要使用它:

XElement xml = XElement.Load(...);
var exam = ExamProduced.ParseElement(xml);

And the actual implementation:

而实际的实施:

public class ExamProduced
{
    public int ExamID { get; set; }
    public DateTime Date { get; set; }
    public int Seed { get; set; }
    public ExerciseCollection Exercises { get; private set; }

    public static ExamProduced ParseElement(XElement answersElement)
    {
        if (answersElement == null) throw new ArgumentNullException("answersElement");
        if (answersElement.Name != "Answers") throw new ArgumentException("element must be an <Answers> element");

        return new ExamProduced
        {
            ExamID = (int)answersElement.Attribute("ExamID"),
            Date = (DateTime)answersElement.Attribute("Date"),
            Seed = (int)answersElement.Attribute("Seed"),
            Exercises = ExerciseCollection.ParseElement(answersElement),
        };
    }
}

public class ExerciseCollection : ReadOnlyCollection<Exercise>
{
    private ExerciseCollection(IEnumerable<Exercise> exercises) : base(exercises.ToList()) { }

    internal static ExerciseCollection ParseElement(XElement answersElement)
    {
        var exercises =
            from objective in answersElement.XPathSelectElements("Summary/Objective")
            join answer in answersElement.Elements("Answer")
                on (int)objective.Attribute("ID") equals (int)answer.Attribute("ObjectiveID")
                into answers
            where answers.Any()
            select Exercise.ParseElements(objective, answers);

        return new ExerciseCollection(exercises);
    }
}

public class Exercise
{
    public int Quantity
    {
        get { return Answers != null ? Answers.Count : 0; }
    }
    public Decimal Score { get; set; }
    public bool IsMakeUp { get; set; }
    public AnswerCollection Answers { get; private set; }

    internal static Exercise ParseElements(XElement objective, IEnumerable<XElement> answerElements)
    {
        return new Exercise
        {
            IsMakeUp = (bool)objective.Attribute("MakeUp"),
            Score = objective.Elements("Details").Select(e => (decimal)e.Attribute("Result")).Last(),
            Answers = AnswerCollection.ParseElements(answerElements),
        };
    }
}

public class AnswerCollection : ReadOnlyCollection<Answer>
{
    private AnswerCollection(IEnumerable<Answer> answers) : base(answers.ToList()) { }

    internal static AnswerCollection ParseElements(IEnumerable<XElement> answerElements)
    {
        var answers =
            from answerElement in answerElements
            select Answer.ParseElement(answerElement);

        return new AnswerCollection(answers);
    }
}

public class Answer
{
    public bool IsCorrect { get; set; }

    internal static Answer ParseElement(XElement answerElement)
    {
        return new Answer
        {
            IsCorrect = (bool)answerElement.Attribute("IsCorrect"),
        };
    }
}

#2


0  

If I understood your requirements correctly, something like this should do the trick:

如果我正确地理解了您的要求,那么这样的事情就可以解决问题:

public static ExamProduced GetExamProduced(XElement xml) {
    var examProduced = new ExamProduced
    {
        ExamID = (int)xml.Attribute("ExamID"),
        Date = (DateTime)xml.Attribute("Date"),
        Seed = (int)xml.Attribute("Seed"),
        Exercises = GetExercises(xml)
    };

    return examProduced;
}

public static List<Exercise> GetExercises(XElement xml) {
    var objs = 
        from objective in xml.Descendants("Objective")
        where (bool)objective.Attribute("Produced")
        let id = (int)objective.Attribute("ID")
        select new Exercise
            {
                ExerciseID = id,
                IsMakeUp = (bool)objective.Attribute("MakeUp"),
                Quantity = (int)objective.Attribute("Quantify"),
                Score = (int)objective.Elements().Last().Attribute("Result"),
                Answers = GetAnswers(xml, id)
            };

        return objs.ToList();
}

public static List<Answer> GetAnswers(XElement xml, int objectiveId) {
    var answers = 
            from answer in xml.Descendants("Answer")
            where (int)answer.Attribute("ObjectiveID") == objectiveId
            select new Answer
              {
                IsCorrect = (bool)answer.Attribute("IsCorrect")
              };
    return answers.ToList();
}

#1


1  

Here's my slightly over-engineered solution for the data you're trying to build. To use it:

这是我为您正在尝试构建的数据略微过度设计的解决方案。要使用它:

XElement xml = XElement.Load(...);
var exam = ExamProduced.ParseElement(xml);

And the actual implementation:

而实际的实施:

public class ExamProduced
{
    public int ExamID { get; set; }
    public DateTime Date { get; set; }
    public int Seed { get; set; }
    public ExerciseCollection Exercises { get; private set; }

    public static ExamProduced ParseElement(XElement answersElement)
    {
        if (answersElement == null) throw new ArgumentNullException("answersElement");
        if (answersElement.Name != "Answers") throw new ArgumentException("element must be an <Answers> element");

        return new ExamProduced
        {
            ExamID = (int)answersElement.Attribute("ExamID"),
            Date = (DateTime)answersElement.Attribute("Date"),
            Seed = (int)answersElement.Attribute("Seed"),
            Exercises = ExerciseCollection.ParseElement(answersElement),
        };
    }
}

public class ExerciseCollection : ReadOnlyCollection<Exercise>
{
    private ExerciseCollection(IEnumerable<Exercise> exercises) : base(exercises.ToList()) { }

    internal static ExerciseCollection ParseElement(XElement answersElement)
    {
        var exercises =
            from objective in answersElement.XPathSelectElements("Summary/Objective")
            join answer in answersElement.Elements("Answer")
                on (int)objective.Attribute("ID") equals (int)answer.Attribute("ObjectiveID")
                into answers
            where answers.Any()
            select Exercise.ParseElements(objective, answers);

        return new ExerciseCollection(exercises);
    }
}

public class Exercise
{
    public int Quantity
    {
        get { return Answers != null ? Answers.Count : 0; }
    }
    public Decimal Score { get; set; }
    public bool IsMakeUp { get; set; }
    public AnswerCollection Answers { get; private set; }

    internal static Exercise ParseElements(XElement objective, IEnumerable<XElement> answerElements)
    {
        return new Exercise
        {
            IsMakeUp = (bool)objective.Attribute("MakeUp"),
            Score = objective.Elements("Details").Select(e => (decimal)e.Attribute("Result")).Last(),
            Answers = AnswerCollection.ParseElements(answerElements),
        };
    }
}

public class AnswerCollection : ReadOnlyCollection<Answer>
{
    private AnswerCollection(IEnumerable<Answer> answers) : base(answers.ToList()) { }

    internal static AnswerCollection ParseElements(IEnumerable<XElement> answerElements)
    {
        var answers =
            from answerElement in answerElements
            select Answer.ParseElement(answerElement);

        return new AnswerCollection(answers);
    }
}

public class Answer
{
    public bool IsCorrect { get; set; }

    internal static Answer ParseElement(XElement answerElement)
    {
        return new Answer
        {
            IsCorrect = (bool)answerElement.Attribute("IsCorrect"),
        };
    }
}

#2


0  

If I understood your requirements correctly, something like this should do the trick:

如果我正确地理解了您的要求,那么这样的事情就可以解决问题:

public static ExamProduced GetExamProduced(XElement xml) {
    var examProduced = new ExamProduced
    {
        ExamID = (int)xml.Attribute("ExamID"),
        Date = (DateTime)xml.Attribute("Date"),
        Seed = (int)xml.Attribute("Seed"),
        Exercises = GetExercises(xml)
    };

    return examProduced;
}

public static List<Exercise> GetExercises(XElement xml) {
    var objs = 
        from objective in xml.Descendants("Objective")
        where (bool)objective.Attribute("Produced")
        let id = (int)objective.Attribute("ID")
        select new Exercise
            {
                ExerciseID = id,
                IsMakeUp = (bool)objective.Attribute("MakeUp"),
                Quantity = (int)objective.Attribute("Quantify"),
                Score = (int)objective.Elements().Last().Attribute("Result"),
                Answers = GetAnswers(xml, id)
            };

        return objs.ToList();
}

public static List<Answer> GetAnswers(XElement xml, int objectiveId) {
    var answers = 
            from answer in xml.Descendants("Answer")
            where (int)answer.Attribute("ObjectiveID") == objectiveId
            select new Answer
              {
                IsCorrect = (bool)answer.Attribute("IsCorrect")
              };
    return answers.ToList();
}