Как создать XSLT, который удаляет из XML только те элементы, значение атрибута которых содержится в списке выбранных значений XPATH - PullRequest
0 голосов
/ 29 апреля 2019

Мне нужно создать XLST, который удаляет ненужные элементы из входного XML.Элементы для фильтрации «Subelement» идентифицируются атрибутом «RelevantForFiltering».Помимо удаления этих элементов, во входном XML-файле «SubelementReference» есть и другие элементы, которые ссылаются на элементы «Subelement» с помощью атрибута «Target».Они также должны быть удалены.

Я уже создал этот XSLT, состоящий из преобразования идентификаторов.Соответствующие шаблоны удаляют нужные элементы из XML.Но теперь я сталкиваюсь с проблемой, что в настоящее время используемая функция «содержит» выбирает также те элементы «SubelementReference», которые содержат только подстроку идентифицированного идентификатора.В приведенном ниже примере «SubelementReference» с целью «SubElem01» также удаляется.Я искал несколько форумов, я не мог найти решение, чтобы понять это.Существуют сопоставимые вопросы, но в этих примерах проверяется, что значение атрибута содержится в списке значений статических атрибутов, которые известны уже при создании XSLT.Заранее благодарю за предложения.

Ввод xml

<?xml version="1.0" encoding="UTF-8"?>
<Document>
  <ListOfElements>
    <Element ID="Element01">
      <UseableSubelements>
        <SubelementReference Target="A-SubElem01, AB" />
        <SubelementReference Target="SubElem01" />
        <SubelementReference Target="A-SubElem02, AB" />
        <SubelementReference Target="A-SubElem03, AB" />
      </UseableSubelements>
    </Element>
    <Element ID="Element02">
      <UseableSubelements>
        <SubelementReference Target="A-SubElem01, AB" />
        <SubelementReference Target="SubElem01" />
        <SubelementReference Target="A-SubElem02, AB" />
      </UseableSubelements>
    </Element>
  </ListOfElements>
  <ListOfSubelements>
    <Subelement ID="A-SubElem01, AB" RelevantForFiltering="true"/>
    <Subelement ID="SubElem01" RelevantForFiltering="false"/>
    <Subelement ID="A-SubElem02, AB" RelevantForFiltering="true"/>
    <Subelement ID="A-SubElem03, AB" RelevantForFiltering="true"/>
  </ListOfSubelements>
</Document>

XSLT

<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" omit-xml-declaration="no"/>

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

<!-- Select items to filter. Separate them by “;” character (tried also to find a solution with tokenize fucntion without any success) -->
<xsl:variable name="SubelementsToFilter">
  <xsl:value-of select="//Subelement[@RelevantForFiltering='true']/@ID" separator=";"/>
</xsl:variable>

<!-- Remove Subelements -> working fine -->
<xsl:template match="Subelement[@RelevantForFiltering='true']"/>
<!-- Remove SubelementReferences -> too many items are removed -->
<xsl:template match="Element/UseableSubelements/SubelementReference[contains($SubelementsToFilter,@Target)]"/>

Текущий вывод XML

<?xml version="1.0" encoding="utf-8"?>
<Document>
    <ListOfElements>
        <Element ID="Element01">
            <UseableSubelements/>
        </Element>
        <Element ID="Element02">
            <UseableSubelements/>
        </Element>
    </ListOfElements>
    <ListOfSubelements>
        <Subelement ID="SubElem01" RelevantForFiltering="false"/>
    </ListOfSubelements>
</Document>

Ожидаемый вывод XML

<?xml version="1.0" encoding="UTF-8"?>
<Document>
  <ListOfElements>
    <Element ID="Element01">
      <UseableSubelements>
            <SubelementReference Target="SubElem01" />
      </UseableSubelements>
    </Element>
    <Element ID="Element02">
      <UseableSubelements>
        <SubelementReference Target="SubElem01" />
      </UseableSubelements>
    </Element>
  </ListOfElements>
  <ListOfSubelements>
    <Subelement ID="SubElem01" RelevantForFiltering="false"/>
  </ListOfSubelements>
</Document>

1 Ответ

1 голос
/ 29 апреля 2019

Если вы действительно хотите использовать contains, вы должны определить переменную следующим образом:

<xsl:variable name="SubelementsToFilter">
  <xsl:text>;</xsl:text>
  <xsl:value-of select="//Subelement[@RelevantForFiltering='true']/@ID" separator=";"/>
  <xsl:text>;</xsl:text>
</xsl:variable>

И тогда совпадение шаблона станет следующим:

<xsl:template match="Element/UseableSubelements/SubelementReference[contains($SubelementsToFilter, concat(';', @Target, ';'))]"/>

Это обойдетсяпроблема A-SubElem01, AB, содержащая SumElem01.

Однако, вам не нужно contains здесь.Вы можете просто определить переменную следующим образом:

<xsl:variable name="SubelementsToFilter" select="//Subelement[@RelevantForFiltering='true']/@ID" />

И тогда совпадение с вашим шаблоном станет следующим:

<xsl:template match="Element/UseableSubelements/SubelementReference[$SubelementsToFilter = @Target]"/>

Однако вы также можете достичь того же результата с помощью ключа.Определите ключ для поиска Subelement следующим образом;

<xsl:key name="Subelements" match="Subelement" use="@ID" />

И тогда совпадение шаблона станет таким:

<xsl:template match="Element/UseableSubelements/SubelementReference[key('Subelements', @Target)[@RelevantForFiltering='true']]"/>

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

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" omit-xml-declaration="no"/>

<xsl:key name="Subelements" match="Subelement" use="@ID" />

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

<!-- Remove Subelements -> working fine -->
<xsl:template match="Subelement[@RelevantForFiltering='true']"/>

<!-- Remove SubelementReferences -> too many items are removed -->
<xsl:template match="Element/UseableSubelements/SubelementReference[key('Subelements', @Target)[@RelevantForFiltering='true']]"/>

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...