Фильтровать результаты оргструктуры - различная глубина иерархии

Я надеюсь, что вы можете указать мне правильное направление в этом вопросе. Я пытаюсь получить отфильтрованный результат нашей оргструктуры, чтобы показать каждый отдел. Образец исходного XML ниже. Я могу реструктурировать исходный код xml, если есть лучший способ сделать это на основе моих требований.

Исходный XML:

<OrgTree>
    <employee ID="1">
        <Name>John</Name>
        <Department>President's Office</Department>
        <employee ID="2">
            <Name>Ron</Name>
            <Department>President's Office</Department>
            <employee ID="3">
                <Name>Don</Name>
                <Department>CEO</Department>
            </employee>
        </employee>
        <employee ID="4">
            <Name>Mike</Name>
            <Department>Finance</Department>
            <employee ID="5">
                <Name>Mark</Name>
                <Department>Accounting</Department>
                <employee ID="6">
                    <Name>Marni</Name>
                    <Department>Accounting</Department>
                </employee>
            </employee>
            <employee ID="7">
                <Name>Mindy</Name>
                <Department>Investments</Department>
            </employee>
        </employee>
    </employee>
</OrgTree>  

Я хотел бы получить вывод в 2 разных формах.

  1. Отфильтруйте по отделу и получите все узлы из этого отдела и дочерних отделов (фильтр по дереву финансов).

Выход 1:

<OrgTree>
    <employee ID="4">
        <Name>Mike</Name>
        <Department>Finance</Department>
        <employee ID="5">
        <Name>Mark</Name>
            <Department>Accounting</Department>
            <employee ID="6">
                <Name>Marni</Name>
                <Department>Accounting</Department>
            </employee>
        </employee>
        <employee ID="7">
        <Name>Mindy</Name>
        <Department>Investments</Department>
        </employee>
    </employee>
</OrgTree>
  1. Отфильтруйте выходные данные по определенному отделу и получите только узлы в этом отделе

Выход 2:

<OrgTree>
<employee ID="5">
    <Name>Mark</Name>
    <Department>Accounting</Department>
    <employee ID="6">
        <Name>Marni</Name>
        <Department>Accounting</Department>
    </employee>
</employee>
</OrgTree>

Я нашел пару постов о фильтрации, как этот результат XSLT Filter с использованием массива XSLT, но моя структура xml достаточно различна, так что мне не повезло, что этот подход работал.

Я нахожусь в SharePoint, поэтому xsl для фильтрации по отделам, которые я пытаюсь, находится ниже, но я не получаю результатов, так как в xml есть только одна родительская строка. Я поиграл с различными способами создания фильтра в шаблоне просмотра строк, какой тип работы, но я хотел бы просто передать отфильтрованные результаты в шаблон просмотра строк без необходимости перебирать все узлы там. Я не знаю, как это сделать, учитывая разную глубину дочерних узлов.

<xsl:for-each select="$Rows[Department = 'CFO']">
     <xsl:call-template name="dvt_1.rowview"/>
</xsl:for-each>

Любая помощь, руководство будет высоко ценится.

1 ответ

Возможно, вы начнете с использования шаблона идентификации, который можно использовать для копирования узлов без изменений.

<xsl:template match="@*|node()" name="identity">
   <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
</xsl:template>

Затем у вас будет шаблон для элементов сотрудников, где вы сможете решить, собираетесь ли вы их копировать или нет. Если бы у них был отдел, соответствующий тому, который вы хотели, или у которого был предок, вы бы скопировали его. В противном случае вы продолжите обработку на дочерних элементах сотрудника.

  <xsl:choose>
     <xsl:when test="ancestor-or-self::employee[Department=$dept]">
        <xsl:call-template name="identity"/>
     </xsl:when>
     <xsl:otherwise>
        <xsl:apply-templates select="employee"/>
     </xsl:otherwise>
  </xsl:choose>

(Где $dept - это параметр, содержащий название отдела, который вы хотите отфильтровать)

Попробуйте это XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:param name="dept" select="'Finance'"/>

   <xsl:template match="@*|node()" name="identity">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="employee">
      <xsl:choose>
         <xsl:when test="ancestor-or-self::employee[Department=$dept]">
            <xsl:call-template name="identity"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:apply-templates select="employee"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

Это должно дать вам "Выход 1". Для "Вывода 2" просто измените условие на это

<xsl:when test="self::employee[Department=$dept]">

Или еще лучше, чтобы просто это

<xsl:when test="Department=$dept">
Другие вопросы по тегам