tags:

views:

76

answers:

3

Hi guys,

I'm a newbie in XSLT & XPath so please forgive me for this simple question.

I have the following XML file:

<?xml version="1.0"?>
    <Configuration serviceName="Just Service" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"&gt;
      <Page name="Books">
        <Instances count="5" />
        <ConfigurationSettings>
          <Setting name="index" value="true" />
          <Setting name="number" value="value1" />
          <Setting name="bookstorage" value="value2"/>
        </ConfigurationSettings>
      </Page>
      <Page name="Magazines">
        <Instances count="7" />
        <ConfigurationSettings>
          <Setting name="index" value="false" />
          <Setting name="number" value="value1" />
          <Setting name="magazinestorage" value="value3"/>
        </ConfigurationSettings>
      </Page>
    </Configuration>

All I want is to change the following values ...

value1 - for number (in two places); value2 - for bookstorage; value3 - for magazinestorage;

... and to remain all the other content unchanged.

For this, I want to use msxsl.exe (Microsoft command line utility). Could you please give me a hint with XSLT style sheet example? How to process initial XML file with XSLT in the most effective way?

Thanks, Rac

A: 

I fear for this usecase and and with xslt it will be easier to build an entire new document from scratch. Or with your programming language of choice you can read the DOM tree and change only those variables (I could show this for Java if necessary).

In other use cases you could let raw xml through the processing. Look here for more info.

Karussell
Karussell, thanks for the answer. Actually, I don't mind if it would be new document from scratch. msxsl.exe has this option. Or I can barely redirect the output. So let it be the new document. So how XSTLT would look like for this case? Thanks,
Racoon
+5  A: 

The way to do this in XSLT would be to have a default template which simply copies the document content, such as:

<xsl:template match="*|@*|text()">
    <xsl:copy>
        <xsl:apply-templates select="*|@*|text()"/>
    </xsl:copy>
</xsl:template>

Then add templates to your stylesheet which will match the particular nodes you want to change. These nodes will override the default copying template above when they match. For example, if you want every number attribute of the element Setting to have the value 314 you would add a template:

<xsl:template match="Setting/@number">
    <-- this copies in an attribute 'number' in place; with different contents -->
    <xsl:copy>314</xsl:copy>    
<xsl:template/>

Both of these templates, plus any others with other substitutions you want to make, will be in your stylesheet, in any order

Vincent Marchetti
Thank you, Vincent!
Racoon
+2  A: 

Here is a sample XSLT 1.0 stylesheet that takes three parameters with the new values:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:sc="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"
  exclude-result-prefixes="sc"
  version="1.0">

  <xsl:param name="p1" select="'foo'"/>
  <xsl:param name="p2" select="'bar'"/>
  <xsl:param name="p3" select="'foobar'"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="sc:Setting[@name = 'number']/@value">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="$p1"/>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="sc:Setting[@name = 'bookstorage']/@value">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="$p2"/>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="sc:Setting[@name = 'magazinestorage']/@value">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="$p3"/>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>
Martin Honnen
Thank you, Martin. It works!
Racoon