XSLT: выберите одного из братьев и сестер - PullRequest
0 голосов
/ 27 сентября 2018

Ввод XML

<skills>
    <skill>
        <id>123</id>
        <name>Java</name>
    </skill>
    <skill>
        <id>123</id>
        <name>Java</name>
        <employee>John Doe</employee>
    </skill>
</skills>

Оба являются узлами навыков и всегда имеют одинаковые значения для id и name узлов, но разницау одного из них есть дополнительный текстовый узел employee . Они могут присутствовать в любом порядке. Первый узел навыка всегда будет присутствовать.В некоторых случаях может также присутствовать второй узел навыка.Если присутствует только первый узел навыка, выберите / распечатайте его.Но если присутствует узел навыка с employee , выберите / распечатайте его.Выход CSV.

Выход

либо

id | name | employee
1 | Java | 

или

id | name | employee
1 | Java | John Doe

Можно ли написать xslt для преобразования?

Благодарим Вас за помощь.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Для меня это похоже на проблему с группировкой:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="sep" as="xs:string" select="' | '"/>

  <xsl:output method="text"/>

  <xsl:template match="skills">
      <xsl:value-of select="distinct-values(skill/*/local-name())" separator="{$sep}"/>
      <xsl:text>&#10;</xsl:text>
      <xsl:for-each-group select="skill" composite="yes" group-by="id, name">
          <xsl:value-of select="id, name, (current-group()/employee)[1]" separator="{$sep}"/>
          <xsl:text>&#10;</xsl:text>
      </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

Онлайн-образец XSLT 3 на https://xsltfiddle.liberty -development.net / pPqsHTZ , если вы ограничены использованием XSLT 2 <xsl:for-each-group select="skill" group-by="string-join((id, name), $sep)"> вместо <xsl:for-each-group select="skill" composite="yes" group-by="id, name">.

0 голосов
/ 27 сентября 2018

Непонятно, что вы ищете, поэтому я догадался.

Попробуйте следующее (я не имел дело с переводом строки).Это не самый красивый способ сделать это, но я думаю, что он обеспечивает то, что вы хотите.По сути, он просто сопоставляет все элементы skill, которые не имеют подэлемента employee, а затем для каждого, если есть соответствующие элементы skill с подэлементом employee, напечатайтеих вместо.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <xsl:apply-templates select="/skills/skill[not(employee)]" />
</xsl:template>

<xsl:template match="skill">
  <xsl:param name="employee" select="/skills/skill[id=current()/id and name=current()/name and employee]" />
  <xsl:choose>
    <xsl:when test="count($employee) > 0">
      <xsl:for-each select="$employee">
        <xsl:value-of select="id" /> | <xsl:value-of select="name" /> | <xsl:value-of select="employee" />
      </xsl:for-each>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="id" /> | <xsl:value-of select="name" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>
...