xmlのデータをそのままコピーしてから要素追加・削除をする
下記にて、xmlのデータをそのまま取得してきたものに対し、要素の追加や削除をしていく。
サンプルコード
XML
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="sample.xsl"?>
<root>
<head>
<title name="タイトル">従業員表</title>
</head>
<data>
<item itemid="1">名前</item>
<item itemid="2">年齢</item>
<item itemid="3">部署</item>
</data>
</root>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/head" >
<head />
</xsl:template>
<xsl:template match="root/data">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<item itemid="4">入社日</item>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
変換結果
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="sample.xsl"?>
<root>
<head />
<data>
<item itemid="1">名前</item>
<item itemid="2">年齢</item>
<item itemid="3">部署</item>
<item itemid="4">入社日</item>
</data>
</root>
解説
要素削除
ここで、root/headの内容を書き換えている。
headのtitle要素を消し、すべての要素がhead要素内から消えたので、<head />としてタグをきれいにした。
<xsl:template match="root/head" >
<head />
</xsl:template>
要素追加
itemの項目を一つ増やそうと、item要素を追加している。
root/dataの内容をコピーして持ってきて、末尾にitem要素を追加している。
<xsl:template match="root/data">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<item itemid="4">入社日</item>
</xsl:copy>
</xsl:template>
要素は追加できたが、下記のようにインデント部分が調整できていない。
<data>
<item itemid="1">名前</item>
<item itemid="2">年齢</item>
<item itemid="3">部署</item>
<item itemid="4">入社日</item>
</data>
テンプレートのノードをitemの最後の位置で呼び出して要素を追加する方法を試してみた。
<xsl:template match="root/data/item[last()]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<item itemid="4">入社日</item>
</xsl:template>
</data>のインデントは改善したが、追加した要素のインデントが上手くいかない。
新規に末尾に追加すると、どの程度のインデントが必要なのかの情報がないのが上手くいかない理由かと。
<xsl:text>で無理やりインデントを作れば何とか整えられる。
<xsl:template match="root/data/item[last()]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<xsl:text>
</xsl:text>
<item itemid="4">入社日</item>
</xsl:template>
