为节点添加属性

问题描述 投票:0回答:2

如果子节点值等于某个字符串,我正在尝试向节点添加属性。

我有一个

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,则应向 Employee 节点添加属性country=32。输出应如下所示:

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

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

    <xsl:include href="Common/identity.xsl"/>
    <xsl:output indent="yes" method="xml"/>

    <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>
</xsl:stylesheet>

任何帮助将不胜感激。我们还可以将

countryid
作为逗号分隔值传递,这样我就可以传递 32,100,然后它应该向所有匹配节点添加属性。

谢谢。

xslt xslt-2.0
2个回答
17
投票

第 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>

解释

  1. 身份规则用于按原样复制每个节点。使用和覆盖身份规则(模板)是最基本、最强大的 XSLT 设计模式。

  2. 只有一个模板可以覆盖特定节点的身份规则 --

    Employee
    元素具有字符串值(转换为数字)的
    countryid
    子元素 32. 该模板向
    countryid
    元素并应用模板来恢复身份规则的活动并按原样复制其他所有内容。
    
    

第 2 部分。

我们还可以将countryid作为逗号传递吗 单独的值,以便我可以通过 32,100 然后应该加上 属性到所有匹配的节点

这个转变

Employee

当应用于同一个 XML 文档(上面)时,会产生所需的正确结果

<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>



9
投票

<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>

输出:

<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> 指令很重要(避免在属性之前输出文本节点)

    

© www.soinside.com 2019 - 2024. All rights reserved.