子ノードの値が文字列と等しい場合、ノードに属性を追加しようとしています。
Main.xmlファイルがあります
<Employees>
<Employee>
<countryid>32</countryid>
<id name="id">1</id>
<firstname >ABC</firstname>
<lastname >XYZ</lastname>
</Employee>
<Employee>
<countryid>100</countryid>
<id name="id">2</id>
<firstname >ddd</firstname>
<lastname >ggg</lastname>
</Employee>
</Employees>
したがって、国IDが32に等しい場合、属性country = 32をEmployeeノードに追加する必要があるとします。出力は次のようになります。
output.xml
<Employees>
<Employee countryid="32">
<countryid>32</countryid>
<id name="id">1</id>
<firstname >ABC</firstname>
<lastname >XYZ</lastname>
</Employee>
<Employee>
<countryid>100</countryid>
<id name="id">2</id>
<firstname >ddd</firstname>
<lastname >ggg</lastname>
</Employee>
</Employees>
次のスクリプトを使用していますが、要素を含む子の後に属性ノードを作成できないというエラーが発生します。
Transform.xsl
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="Employees/Employee/countryid[.=32']">
<xsl:attribute name="countryid">32</xsl:attribute>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
どんな助けでもありがたいです。また、countryidをコンマ区切りの値として渡して、32,100を渡すことができます。そうすると、一致するすべてのノードに属性が追加されます。
ありがとう。
Dimitreの良い答えに加えて、XSLT2.0スタイルシート:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="pCountry" select="'32,100'"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Employee[countryid = tokenize($pCountry,',')]">
<Employee countryid="{countryid}">
<xsl:apply-templates select="@*|node()"/>
</Employee>
</xsl:template>
</xsl:stylesheet>
出力:
<Employees>
<Employee countryid="32">
<countryid>32</countryid>
<id name="id">1</id>
<firstname>ABC</firstname>
<lastname>XYZ</lastname>
</Employee>
<Employee countryid="100">
<countryid>100</countryid>
<id name="id">2</id>
<firstname>ddd</firstname>
<lastname>ggg</lastname>
</Employee>
</Employees>
注:シーケンスとの実存的比較、パターン内のパラメーター/変数参照。
countryid
が常に最初の子であると仮定する他のアプローチ:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:param name="pCountry" select="'32,100'"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="countryid[. = tokenize($pCountry,',')]">
<xsl:attribute name="countryid">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
注:今xsl:strip-space
命令は重要です(属性の前にテキストノードを出力することは避けます)
パート1。
したがって、国IDが32に等しい場合、属性country = 32をEmployeeノードに追加する必要があるとします。
この変換:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Employee[countryid=32]">
<Employee countryid="{countryid}">
<xsl:apply-templates select="@*|node()"/>
</Employee>
</xsl:template>
</xsl:stylesheet>
提供されたXMLドキュメントに適用した場合:
<Employees>
<Employee>
<countryid>32</countryid>
<id name="id">1</id>
<firstname >ABC</firstname>
<lastname >XYZ</lastname>
</Employee>
<Employee>
<countryid>100</countryid>
<id name="id">2</id>
<firstname >ddd</firstname>
<lastname >ggg</lastname>
</Employee>
</Employees>
必要な正しい結果を生成します:
<Employees>
<Employee countryid="32">
<countryid>32</countryid>
<id name="id">1</id>
<firstname>ABC</firstname>
<lastname>XYZ</lastname>
</Employee>
<Employee>
<countryid>100</countryid>
<id name="id">2</id>
<firstname>ddd</firstname>
<lastname>ggg</lastname>
</Employee>
</Employees>
説明:
アイデンティティルール は、すべてのノードをそのままコピーするために使用されます。 IDルール(テンプレート)の使用とオーバーライドは、最も基本的で強力なXSLTデザインパターンです。
特定のノードのIDルールをオーバーライドするテンプレートは1つだけです-Employee
子を持つcountryid
要素文字列値(数値に変換)32。このテンプレートは、countryid
属性をEmployee
要素に追加し、テンプレートを適用してIDルールのアクティビティを再開し、その他すべてをそのままコピーします。
パート2。
また、countryidをコンマ区切りの値として渡して、32,100を渡すことができるようにしてから、一致するすべてのノードに属性を追加する必要があります。
この変換:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pIds" select="'32,100'"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Employee">
<Employee>
<xsl:if test=
"contains(concat(',',$pIds,','),
concat(',',countryid,',')
)">
<xsl:attribute name="countryid">
<xsl:value-of select="countryid"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="@*|node()"/>
</Employee>
</xsl:template>
</xsl:stylesheet>
同じXMLドキュメント(上記)に適用すると、必要な正しい結果が生成されます:
<Employees>
<Employee countryid="32">
<countryid>32</countryid>
<id name="id">1</id>
<firstname>ABC</firstname>
<lastname>XYZ</lastname>
</Employee>
<Employee countryid="100">
<countryid>100</countryid>
<id name="id">2</id>
<firstname>ddd</firstname>
<lastname>ggg</lastname>
</Employee>
</Employees>