2011-04-29 17 views
6

No puedo cambiar un elemento en Web.config con MSDeploy. Mi parameters.xml archivo:Cómo cambiar un elemento XML en un espacio de nombres con el archivo MSDeploy Parameters.xml?

<parameterEntry 
    kind="XmlFile" 
    scope="\\web.config$" 
    match="//spring/objects/object[@id='CultureResolver']/@type" /> 

La sección pertinente de Web.config:

<spring> 
    <objects xmlns="http://www.springframework.net"> 

     <object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver, Spring.Web"> 
      <!--configure for server--> 
      <property name="DefaultCulture" value="en" /> 
     </object> 
    </objects> 
</spring> 

Respuesta

7

el problema es la declaración de espacio de nombres en el elemento <objects/>. Su consulta XPath no tiene una coincidencia porque no hay ningún elemento <objects/> con un espacio de nombres vacío (que es lo que busca la consulta).

Ahora, especificando los espacios de nombres XML en XPath es un tema complicado (en este caso es incluso imposible), por lo que te sugiero que utilice esta expresión en su lugar:

"//spring/*/*[@id='CultureResolver']/@type" 

HTH ...

+0

Grandes gracias, funciona para mí también! Para aquellos que buscan en Google: tenían el mismo problema con los parámetros de implementación.xml y Mvc.Sitemap. Debido a xmlns en la importación de IIS nodo mvcSiteMap no fue capaz de igualar XPath como esto: "/ mvcSiteMap/mvcSiteMapNode/mvcSiteMapNode [@ title = 'Mi título']/@ url". – Kirill

+0

Su solución definitivamente trabajó, y os upvoted cuando encontré primero su respuesta, pero recientemente he descubierto que estás equivocado que es imposible escribir una consulta XPath que especifica los espacios de nombres XML correctamente, y que lo haga de una manera que Web Implementar apoyos. –

7

El Truco XPath

Su ejemplo fue un poco complicado (al principio). Pero esta consulta XPath, mientras que mucho más tiempo, debería funcionar:

//spring/*[local-name() = 'objects' and namespace-uri() = 'http://www.springframework.net']/*[@id='CultureResolver' and local-name() = 'object' and namespace-uri() = 'http://www.springframework.net']/@type 

descubrí este truco en this answer a la cuestión de forma c# - Declare namespaces within XPath expression, pero en realidad lo descubrí después de que ya había publicado esta respuesta (originalmente).

He dejado la mayor parte de mi respuesta original a continuación y también he añadido secciones adicionales sobre cómo mi respuesta original es incorrecta.

Mi Ejemplo

quería hacer esto por NLog; he aquí un ejemplo de mi archivo NLog.config:

<?xml version="1.0" encoding="utf-8" ?> 
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true"> 

    ... 

    <targets> 
    <target name="HipChat" xsi:type="MethodCall" className="DbNecromancer.Logging, DbNecromancer" methodName="SendHipChatRoomNotification"> 
     <parameter layout="1234567" name="roomId" /> 
     <parameter layout="blah-blah-blah" name="authToken" /> 
     <parameter layout="${message-layout}" name="message" /> 
     <parameter layout="${level}" name="nLogLevel" /> 
    </target> 
    </targets> 

    ... 
</nlog> 

Aquí está la consulta XPath relevante de mi archivo parameters.xml para cambiar el atributo del elemento layoutparameter con un valor de "roomid" para la name atributo:

/nlog/targets/target[@name='HipChat']/parameter[@name='roomId']/@layout

Usted puede confirmar que el XPath anterior no coincide con el atributo deseado usando this free online XPath tester. ¡También puedes confirmar que falla al usar Web Deploy!

Pero yo era capaz de conseguir que esto funcione, tanto en el probador de línea y desde la web de despliegue, sin necesidad de utilizar comodines o retirar la declaración de espacio en NLog.config. El truco fue agregar un prefijo de espacio de nombres.

Aquí están las líneas modificadas en NLog.config:

<nlog:nlog xmlns:nlog="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true"> 
    ... 
</nlog:nlog> 

Aquí está la consulta XPath modificación:

/nlog:nlog/targets/target[@name='HipChat']/parameter[@name='roomId']/@layout 

Su Ejemplo

no podía conseguir su ejemplo para trabajar en el probador en línea, simplemente añadiendo un prefijo donde su ejemplo está usando un espacio de nombres (y no tengo un proyecto que use Spring). La salida del probador cuando intento sólo tiene que añadir un prefijo:

ERROR - No se ha podido evaluar la expresión XPath: Prefijo debe resolverse en un Espacio de nombres: primavera

Sin embargo, yo era capaz de conseguirlo para trabajar haciendo lo siguiente (que creo que podría ser 'correcto').

He aquí las líneas en el código XML que cambiaron:

<spring xmlns="" xmlns:spring="http://www.springframework.net"> 
    <spring:objects> 
     ... 
    </spring:objects> 

Aquí está la consulta XPath modificación:

/spring/spring:objects/object[@id='CultureResolver']/@type 

Por qué 'Mi ejemplo' y 'Tu Ejemplo' son (sutilmente) incorrecto

El problema, como parezco (apenas) lo entiendo, es que declarar un espacio de nombres sin un prefijo es muy diferente a declarar uno con un prefijo.

La declaración de un espacio de nombres con un prefijo simplemente declara el espacio de nombres y su prefijo, pero no cambia el espacio de nombres de cualquier elemento.

Declaración de un espacio de nombres sin un prefijo hace que ese espacio de nombres del espacio de nombres predeterminado, tanto para el elemento en el que su definido y para todos los elementos secundarios de ese elemento.

Así que, por su ejemplo, podría modificar la siguiente línea en su XML y su consulta XPath original, va a trabajar:

<objects xmlns:spring="http://www.springframework.net"> 

[Sólo añadir el prefijo spring al espacio de nombres.]

Eso es debido a (o está de acuerdo con mi hipótesis de trabajo) que la adición del prefijo a la declaración de espacio de nombres sin añadir también el prefijo al elemento objects (y todos sus hijos) es 'significativamente' modificar el código XML porque está eliminando los elementos del espacio de nombres .

Para añadir correctamente un prefijo sin modificar la semántica del XML, el XML debe ser el siguiente:

<spring> 
    <spring:objects xmlns:spring="http://www.springframework.net"> 
     <spring:object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver, Spring.Web"> 
      <!--configure for server--> 
      <spring:property name="DefaultCulture" value="en" /> 
     </spring:object> 
    </spring:objects> 
</spring> 

Y su consulta XPath debe ser como este:

//spring/spring:objects/spring:object[@id='CultureResolver']/@type 

El único problema es que eso no funciona (en the online tester, y probablemente no sea con MSDeploy).

Lo anterior no funciona porque los motores de XPath requieren espacios de nombres para ser registrados (separado de los espacios de nombres declarados en el propio documento XML). Pero, como parece que tanto Web Deploy como el probador en línea hacen, cualquier declaración en el elemento raíz del documento XML se registra automáticamente. Y eso es muy útil ya que no conozco ninguna forma de registrar espacios de nombres cuando se usa la transformación de parámetros de Web Deploy.

Para una explicación más detallada ver las respuestas a mi pregunta relacionada Do XML namespaces need to be declared in the root element to be matchable by an XPath query?.

Tu (Corregido) Ejemplo

XML:

<spring xmlns:spring="http://www.springframework.net"> 
    <spring:objects> 
     <spring:object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver, Spring.Web"> 
      <!--configure for server--> 
      <spring:property name="DefaultCulture" value="en" /> 
     </spring:object> 
    </spring:objects> 
</spring> 

consulta XPath:

//spring/spring:objects/spring:object[@id='CultureResolver']/@type 

Conclusión

Si no le importa consultas XPath largos, utilice el truco en la cima. De lo contrario, modifique las declaraciones del espacio de nombres XML para que incluyan un prefijo y estén ubicadas en el elemento raíz de su documento XML.

+2

Eres un caballero y un erudito, gracias. Acabo de sacarme de un aprieto durante una puesta en marcha. – Michael12345

Cuestiones relacionadas