Фильтровать результаты оргструктуры - различная глубина иерархии
Я надеюсь, что вы можете указать мне правильное направление в этом вопросе. Я пытаюсь получить отфильтрованный результат нашей оргструктуры, чтобы показать каждый отдел. Образец исходного 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:
<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>
- Отфильтруйте выходные данные по определенному отделу и получите только узлы в этом отделе
Выход 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">