добавление атрибута в узел
Я пытаюсь добавить атрибут к узлу, если значение дочернего узла равно некоторой строке.
у меня есть 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>
Итак, скажем, если идентификатор страны равен 32, то он должен добавить атрибут country=32 в узел Employee. Вывод должен быть следующим:
выход.в 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>
Я использую следующий скрипт, но получаю ошибку, что узел атрибута не может быть создан после дочерних элементов containing элемент.:
трансформировать.язык 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, а затем добавить атрибут ко всем соответствующим узлам.
спасибо.
2 ответов
в дополнение к хорошему ответу Димитра, таблица стилей XSLT 2.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>
Примечание: Existencial сравнение с последовательностью, param / переменной ссылки в шаблонах.
другой подход, предполагающий 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.
скажем, если код страны равен 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>
объяснение:
на правила удостоверения используется для копирования всех узлов, как есть. Использование и переопределение правила идентификации (шаблона) является наиболее фундаментальным и мощным шаблоном проектирования XSLT.
существует только один шаблон, который переопределяет правило идентификации для определенных узлов --
Employee
элементы, которые имеютcountryid
ребенок с строковое значение (преобразованное в число) 32. Этот шаблон добавляет доEmployee
элемент и применяет шаблоны для возобновления действия правила идентификации и копирования всего остального как есть.
Часть 2.
также мы можем передать countryid как запятую seprated значения, чтобы я мог передать 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>