Re: [xml] xml find and replace



Hi

I've nearly created an XLST that does nearly what I want

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

<xsl:template match="//control[name='DelaySeconds']/numeric/max">
<xsl:element name="{name(.)}">
        <xsl:value-of select="translate(string(.), '110', '5')" />
</xsl:element>
</xsl:template>

<xsl:template match="//control[name='DelaySeconds']/numeric/scalemax">
<xsl:element name="{name(.)}">
        <xsl:value-of select="translate(string(.), '110', '5')" />
</xsl:element>
</xsl:template>

</xsl:stylesheet>

This replace the strings

<max>110</max>
<scalemax>110</scalemax>

with

<max>55</max>
<scalemax>55</scalemax>

but what I want is

<max>5</max>
<scalemax>5</scalemax>

I've tried using replace instead of translate but I get the error message

xmlXPathCompOpEval: function replace not found
XPath error : Unregistered function

Any ideas how to get round that?

Cheers
Stuart.




On Fri, Jul 13, 2012 at 11:40 AM, stuart shepherd <jonny wark googlemail com> wrote:
Hi

I've had a look at this and I'm not sure it does it exactly what I want.

My Main XML will look something like this

<control>
<name>ControlName</name>
<max>50</max>
....
</control>

The control name is unique to that control, which is what I use to identify it.
There will several controls in the XML files.
I need to change one or two of the max values of them, not all, and not all to the same value.
The control element will contain other elements other than max.

After looking at your example I thought I could add an element to my sub set XML that looks something like this.

<override>
    <name>ControlName</name> <!-- this will be the unique name of the control whose values I want to change -->
   <max>100</max> <!-- the value I want to change -->
</override>

So what I want to do is look at the subset XML file and if there is an override element find the control that it names and then overwrite the value that is specified within the override element, it may be other elements other than max, and maybe more than one. If it's easier I could several overrides each one containing only a single override value.

Is this possible with XSLT?

Thank you for your help.

Stuart.


On Thu, Jul 12, 2012 at 7:07 PM, Piotr Sipika <piotreks optonline net> wrote:
On 07/12/2012 09:53 AM, stuart shepherd wrote:
> Searching the web I've seen some examples in XSLT on how to
> do something like this, but I have never used XSLT. Does anyone know if
> there is a way to do this in XML.

XSLT is your best bet.

Here's a sample stylesheet which will:
 - change the name of all elements named 'old' to 'new'
 - change the name of all elements with an attribute named 'old' to 'new'

---- BEGIN stylesheet ----

<?xml version="1.0" standalone="yes"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml"/>

  <!-- Template matches every node and attribute-->
  <xsl:template match="node()|@*">

    <xsl:choose>
      <!-- if name of element is 'old' or element contains an attribute
           named 'old', replace it with 'new' -->
      <xsl:when test="@old or name(.)='old'">
        <xsl:variable name="old_node" select="node()"/>
        <xsl:variable name="old_value" select="./text()"/>
        <xsl:variable name="attributes" select="@*"/>
        <xsl:variable name="children" select="./*"/>

        <!-- create a 'new' element with attributes and children from
             the 'old' node, with its old value -->
        <xsl:element name="new">
          <xsl:copy-of select="$attributes|$children"/>
          <xsl:value-of select="$old_value"/>
        </xsl:element>
      </xsl:when>

      <!-- else, just copy the node/attributes -->
      <xsl:otherwise>
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

---- END stylesheet ----

Sample XML:
<?xml version="1.0" standalone="yes"?>
<swap>
  <old attr="attr1">This used to be inside the old node
    <old_child1>This is old_child1</old_child1>
  </old>
  <foo attr="attr2">This is just a middle element...</foo>
  <foo old="old attribute"/>
</swap>

Output of stylesheet processing using xsltproc (libxml 20708, libxslt
10126 and libexslt 815):

$ xsltproc swap.xsl swap.xml
<?xml version="1.0"?>
<swap>
  <new attr="attr1"><old_child1>This is old_child1</old_child1>This used
to be inside the old node
  </new>
  <foo attr="attr2">This is just a middle element...</foo>
  <new old="old attribute"/>
</swap>


You can modify the attribute match criteria (@old) to actually evaluate
its contents ([ old='old_parent']), etc...

Hope this helps.

Piotr




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]