transformar - Atravesando un gráfico de objetos C#arbitrario usando XPath/aplicando transformaciones XSL
xsl:template (4)
He estado buscando un componente que me permita pasar un objeto C # arbitrario a una transformación XSL.
La forma ingenua de hacer esto es serializar el gráfico de objetos usando un XmlSerializer; sin embargo, si tiene un gráfico de objeto grande, esto podría causar problemas en lo que respecta al rendimiento. Cuestiones como referencias circulares, cargas flojas, proxies, etc. pueden enturbiar aún más las aguas aquí.
Un mejor enfoque es tener algún tipo de clase de Adaptador que implemente IXPathNavigable y XPathNavigator. Uno de los ejemplos que me he encontrado es el ObjectXPathNavigator de Byte-Force ; sin embargo, la mayoría de su documentación clave está en ruso, y mis pruebas iniciales parecen indicar que tiene algunos caprichos e idiosincrasias.
¿Alguien sabe de (a) los recursos (reseñas, tutoriales, publicaciones en blogs, etc.) sobre este particular en inglés o (b) cualquier otra alternativa que ofrezca la misma funcionalidad o una similar?
Parece que el problema que intentas resolver es bastante interesante.
A primera vista, le sugiero que escriba su propia implementación de un descendiente XPathNavigator
: solo hay 20 métodos impares para escribir, y ninguno de ellos tiene una firma particularmente difícil.
Una implementación ingenua que utiliza la reflexión no almacenada en caché sería lenta (ish) pero funcionaría bien como una prueba de concepto y podría realizar cambios para mejorar el rendimiento si eso se convierte en un problema.
Sin embargo ...
... Creo que puede encontrarse con algunas dificultades que se derivan de su enfoque, no de ningún detalle de implementación.
Un archivo XML es (por naturaleza) una jerarquía simple de elementos y atributos; no hay bucles (ciclos aka) en el gráfico de nodos.
Una expresión XPath puede incluir el operador " //
", lo que significa en general buscar a profundidad ilimitada. (Para obtener una definición exacta, consulte la sección 2.5 de XPath 1.0 .)
Si aplicaste tal expresión a un gráfico de objetos con referencias cruzadas (también conocido como ciclos de objetos), entonces corres el riesgo de que el evaluador XPath entre en un ciclo infinito cuando intenta enumerar recursivamente un gráfico efectivamente infinito.
Es posible que pueda XPathNavigator
este problema de alguna manera haciendo un seguimiento de los nodos principales en su XPathNavigator
y lanzando una excepción si se detecta un bucle, pero no estoy seguro de cuán viable será.
Dado que el gráfico de objeto puede ser cíclico, no es posible crear una estructura basada en Árbol. Su mejor apuesta es representar el gráfico de objetos por sus componentes más simples: nodos y vectores.
Más específicamente, convierta cada nodo (objeto) en un elemento con una ID única (tal vez proporcionada por el método GetHashCode () de C #). Las referencias a otros objetos (vectores) se manejarían haciendo referencia a la ID del objeto.
Clases de ejemplo (tenga en cuenta que no sé C #, por lo que mi sintaxis puede estar un poco fuera):
public class SomeType {
public int myInt { get; set; }
}
public class AnotherType {
public string myString { get; set; }
public SomeType mySomeType { get; set; }
}
public class LastType {
public SomeType mySomeType { get; set; }
public AnotherType myAnotherType { get; set; }
}
public class UserTypes{
static void Main()
{
LastType lt = new LastType();
SomeType st = new SomeType();
AnotherType atype = new AnotherType();
st.myInt = 7;
atype.myString = "BOB";
atype.mySomeType = st;
lt.mySomeType = st;
lt.myAnotherType = atype;
string xmlOutput = YourAwesomeFunction(lt);
}
}
Entonces, esperaríamos que el valor de xmlOutput fuera algo como esto (tenga en cuenta que los valores de ID elegidos son completamente sintéticos):
<ObjectMap>
<LastType id="0">
<mySomeType idref="1" />
<myAnotherType idref="2" />
</LastType>
<SomeType id="1">
<myInt>7</myInt>
</SomeType>
<AnotherType id="2">
<myString>BOB</myString>
<mySomeType idref="1" />
</AnotherType>
</ObjectMap>
Hay un (muy) viejo artículo de MSDN llamado XPath Query Over Objects con ObjectXPathNavigator que implementa una clase similar (también llamado ObjectXPathNavigator, curiosamente). Utilicé esto hace siglos para consultar algunos datos de Visual SourceSafe y crear un feed RSS del registro de cambios, y funcionó bastante bien. Sin embargo, no hice XSLT con él, así que no estoy seguro de si eso funciona o no. Además, tenga en cuenta que fue escrito para Framework 1.0, por lo que puede necesitar actualizarlo para frameworks más recientes. Además, puede haber mejores formas de hacerlo ahora, pero le daría un punto de partida (y el artículo hace un buen trabajo al explicar cómo funciona).
Podrías probar algo como esto:
http://code.google.com/p/antix-software/wiki/AntixReflectionQuery