开发者

Modify attribute of certain XML elements

I would like to modify an attribute of a very long xml like this:

<element index="0">
    <subelement bla="asdf" />
    <subelement bla="asdf" />
</element>
<element index="1">
    <subelement bla="asdf" />
    <subelement bla="asdf" />
</element>
...

I need to add N the value of each index attribute. Say N=5. The result would be:

<element index="5">
    <subelement bla="asdf" />
    &l开发者_C百科t;subelement bla="asdf" />
</element>
<element index="6">
    <subelement bla="asdf" />
    <subelement bla="asdf" />
</element>
...

What's the easiest way to do this? I presume it would be with XSLT, but I don't know how to do it.

Thanks!


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

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

  <!-- except "element" nodes -->
  <xsl:template match="element">
    <xsl:copy>
      <xsl:attribute name="index">
        <xsl:value-of select="@index + 5"/>
      </xsl:attribute>
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>


svick answer it's a good solution. Just in case you have to keep exact structure, try:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:param name="increment" select="5" />

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

<xsl:template match="node()[not(node())]">
 <xsl:element name="{name()}" >
  <xsl:apply-templates select="@*" />
 </xsl:element>
</xsl:template>

<xsl:template match="element/@index">
 <xsl:attribute name="index">
  <xsl:value-of select="$increment + ." />
 </xsl:attribute>
</xsl:template>

</xsl:stylesheet>


Here's a somewhat general solution for an arbitrary attribute to increase:

#!/bin/bash

PROG=$(basename $0 )
: ${TMPDIR:=/tmp}
:  ${INC:=1}
TMPFILE=$TMPDIR/$PROG.$$.xml

function usage() {

cat <<!
$PROG <attribute>  <input-xml>

Increases all attributes named <attribute> in the <input-xml> XML file by 1 ( or \$INC ) 
!
exit 1
}

[ $# -eq 2 ] || usage

{
cat <<!
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>

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

  <!-- except "attribute-of-interest" node -->
  <xsl:template match="@$1">
    <xsl:attribute name="$1">
        <xsl:value-of select=". + $INC"/>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>
!
}  xsltproc /dev/stdin $2 > $TMPFILE  && mv $TMPFILE $2

Clearly this is svick's answer. I changed the XSL somewhat to cover multiple attributes in the target element. FWIW, I templatized it using bash.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜