Linq a XML y múltiples transformaciones
-
06-07-2019 - |
Pregunta
Tengo problemas para asimilar algo en Linq; tal vez alguien pueda darme algunos consejos.
Tengo XML que necesito transformar a un nuevo XML.El problema con esto es que necesito varias iteraciones de transformación para hacerlo bien.
La fuente se vería así:
<Meals>
<ketchup/>
<steak/>
<mustard/>
<thigh/>
<fillet/>
<penne/>
<drumstick/>
<steak/>
<ketchup/>
<fillet/>
<fillet/>
<macaroni/>
<drumstick/>
<thigh/>
<ketchup/>
<thigh/>
<fillet/>
</Meals>
Lo que me gustaría que esto terminara siendo es:
<Meals>
<Meal>
<ketchup/>
<steak/>
<mustard/>
<thigh/>
</Meal>
<Meal>
<fillet/>
<penne/>
<drumstick/>
</Meal >
<Meal>
<steak/>
<ketchup/>
</Meal>
<Meal>
<fillet/>
</Meal>
<Meal>
<fillet/>
<macaroni/>
<drumstick/>
</Meal>
<Meal>
<thigh/>
<ketchup/>
</Meal>
<Meal>
<thigh/>
<fillet/>
</Meal>
</Meals>
La lógica aquí es que:
<steak>
y<fillet>
son carnes de carne: cualquier cosa que ocurra antes o después de ellas que no es una parte de carne de res parte de la comida siempre que aún no sea parte de otra comida.Si la carne de vacuno aparece después de la carne de vacuno, se crea una nueva comida en el elemento de la nueva carne de vacuno.<thigh>
y<drumstick>
son carnes de pollo: cualquier cosa que ocurra antes o después de ellas que no es una carne de pollo es parte de la comida siempre que no sea parte de otra comida.Si la carne de pollo aparece después de la carne de pollo, se crea una nueva comida en el elemento de la nueva carne de pollo.<macaroni>
y<penne>
son pastas cualquier cosa que ocurra antes o después de ellos que no es una pasta es parte de la comida siempre que aún no sea parte de otra comida.Si la pasta aparece después de una pasta, se crea una nueva comida en el elemento de la nueva pasta.<ketchup>
y<mustard>
son condimentos: pueden ser parte de cualquier comida.
Comencé con ElementsAfterSelf, ElementsBeforeSelf y TakeWhile, pero me encuentro con obstáculos al no entender cómo realizar lo anterior.Estoy usando VB.NET y Linq, pero puedo leer C#.
¿Alguna idea o sugerencia?
Solución
Recibí una buena respuesta de otro foro y aquí está la final:
Dim meals As XElement = <Meals>
<ketchup/>
<steak/>
<mustard/>
<thigh/>
<fillet/>
<macaroni/>
<drumstick/>
<thigh/>
<ketchup/>
<thigh/>
<fillet/>
</Meals>
Dim newMeals As XElement = <Meals/>
Dim meal As XElement = <Meal/>
Dim hasBeef As Boolean
Dim hasChicken As Boolean
For Each m In meals.Descendants()
Select Case m.Name
Case Is = "steak", "fillet"
If hasBeef Then
newMeals.Add(meal)
meal = <Meal/>
hasChicken = False
Else
hasBeef = True
End If
meal.Add(m)
Case Is = "drumstick", "thigh"
If hasChicken Then
newMeals.Add(meal)
meal = <Meal/>
hasBeef = False
Else
hasChicken = True
End If
meal.Add(m)
Case Else
meal.Add(m)
End Select
Next
newMeals.Add(meal)
Otros consejos
Puede encontrar LINQPad útil. Le daría una oportunidad a su problema, pero no tengo clara la lógica de combinación que especificó, ya que no coincide con el ejemplo tal como lo entiendo (por ejemplo, ¿por qué no hay mostaza en cada comida?)