2010-01-22 11 views
7

Estamos obteniendo un documento XML de un proveedor que necesitamos para realizar una transformación XSL al usar su hoja de estilos para que podamos convertir el HTML resultante en un PDF. La hoja de estilo real se referencia en un atributo href de la definición ?xml-stylesheet en el documento XML. ¿Hay alguna forma de que pueda obtener esa URL usando C#? No confío en que el proveedor no cambie la URL y, obviamente, no quiero codificarla.¿Cómo puedo obtener el valor del atributo href de un nodo <? Xml-stylesheet>?

El inicio del archivo XML con la ?xml-stylesheet elemento completo es el siguiente:

<?xml version="1.0" encoding="utf-8"?> 
<?xml-stylesheet type="text/xsl" href="http://www.fakeurl.com/StyleSheet.xsl"?> 

Respuesta

2

LINQ al código XML:

XDocument xDoc = ...; 

var cssUrlQuery = from node in xDoc.Nodes() 
     where node.NodeType == XmlNodeType.ProcessingInstruction 
     select Regex.Match(((XProcessingInstruction)node).Data, "href=\"(?<url>.*?)\"").Groups["url"].Value; 

o LINQ a objetos

var cssUrls = (from XmlNode childNode in doc.ChildNodes 
        where childNode.NodeType == XmlNodeType.ProcessingInstruction && childNode.Name == "xml-stylesheet" 
        select (XmlProcessingInstruction) childNode 
        into procNode select Regex.Match(procNode.Data, "href=\"(?<url>.*?)\"").Groups["url"].Value).ToList(); 

xdoc .XPathSelectElement() no funcionará, ya que, por alguna razón, no se puede convertir XElement a XProcessin gInstruction.

+0

Preferiría usar DOM o LinqToXml, pero cuanto más excavo, más parece que esta podría ser la única opción. –

+0

Sí, he estado luchando con eso, también. Si hubiera alguna forma de tratar la ProcessingInstruction como un elemento, sería más simple. –

1

Para hallar el valor de uso de un analizador XML adecuada se podría escribir algo como esto:


using(var xr = XmlReader.Create(input)) 
{ 
    while(xr.Read()) 
    { 
     if(xr.NodeType == XmlNodeType.ProcessingInstruction && xr.Name == "xml-stylesheet") 
     { 
      string s = xr.Value; 
      int i = s.IndexOf("href=\"") + 6; 
      s = s.Substring(i, s.IndexOf('\"', i) - i); 
      Console.WriteLine(s); 
      break; 
     } 
    } 
} 
3

También puede utilizar XPath. Teniendo en cuenta un XmlDocument cargado con su fuente:

XmlProcessingInstruction instruction = doc.SelectSingleNode("//processing-instruction(\"xml-stylesheet\")") as XmlProcessingInstruction; 
if (instruction != null) { 
    Console.WriteLine(instruction.InnerText); 
} 

A continuación, sólo PARSE InnerText con expresiones regulares.

+2

Usando esta expresión XPATH y no necesita hacer ningún Regex: 'translate (subserie-after (proceso-instrucción ('xml-stylesheet'), 'href ='), '"', '')' –

3

Como una instrucción de procesamiento puede tener cualquier contenido, formalmente no tiene ningún atributo. Pero si sabe que hay atributos "pseudo", como en el caso de una instrucción de procesamiento xml-stylesheet, entonces puede usar el valor de las instrucciones de procesamiento para construir el marcado de un elemento y analizarlo con el analizador XML. :

XmlDocument doc = new XmlDocument(); 
    doc.Load(@"file.xml"); 
    XmlNode pi = doc.SelectSingleNode("processing-instruction('xml-stylesheet')"); 
    if (pi != null) 
    { 
     XmlElement piEl = (XmlElement)doc.ReadNode(XmlReader.Create(new StringReader("<pi " + pi.Value + "/>"))); 
     string href = piEl.GetAttribute("href"); 
     Console.WriteLine(href); 
    } 
    else 
    { 
     Console.WriteLine("No pi found."); 
    } 
1
private string _GetTemplateUrl(XDocument formXmlData) 
{ 
    var infopathInstruction = (XProcessingInstruction)formXmlData.Nodes().First(node => node.NodeType == XmlNodeType.ProcessingInstruction && ((XProcessingInstruction)node).Target == "mso-infoPathSolution"); 
    var instructionValueAsDoc = XDocument.Parse("<n " + infopathInstruction.Data + " />"); 
    return instructionValueAsDoc.Root.Attribute("href").Value; 
} 
+0

One tiene que usar 'xml-stylesheet' en lugar de' mso-infoPathSolution', pero luego funciona para mí. Toma el primer elemento y devuelve el resultado. – testing

0

XmlProcessingInstruction hoja de estilo = doc.SelectSingleNode ("instrucción de procesamiento ('xml-stylesheet')") como XmlProcessingInstruction;

Cuestiones relacionadas