Как удалить узлы XML в зависимости от значения атрибута других узлов - PullRequest
0 голосов
/ 23 октября 2019

У меня есть XML, похожий на этот:

  <pack>
    <titlesPacks>
      <StoryPack id="1111111">
        <value>A</value>
      </StoryPack>
      <StoryPack id="2222222">
        <value>F</value>
      </StoryPack>
    </titlesPacks>
    <referenceTable>
       <TitleReference id="1111111" />
       <TitleReference id="2222222" />
    </referenceTable>
  </pack>

Мне нужно скопировать XML-файл, но:

  • удалить StoryPack узлов, где value узел имеет определенное значение (например, A, B, C). Эта часть уже в порядке

  • удалить 'TitleReference nodes where id attribute value is equal to id attribute value of' StoryPack узлов, удаленных выше

Я незнаю, как сделать второй: я пытался с Key, но не работает:

Мой текущий XSL:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:data="http://example.com/data" exclude-result-prefixes="data">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="titleId" match="StoryPack" use="@id"/>

    <!-- Values for wich nodes must be deleted -->
    <data:data xmlns="">
        <value>A</value>
        <value>B</value>
        <value>C</value>
    </data:data>

    <xsl:variable name="values" select="document('')/xsl:stylesheet/data:data/value"/>


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


<!-- Delete nodes with specific values -->
    <xsl:template match="StoryPack[value = $values]"/>

<!-- Dlete nodes with id from specific values -->
<xsl:template match="TitleReference[StoryPack[key('titleId', @id)/value = $values]]" />
</xsl:stylesheet>

Спасибо за вашу помощь!

=============

После ответов @ michael.hor257k: мой исходный XML немного сложнее, поэтому, вероятно, он не работает в моем случае: Xpath ofзначение более глубокое: / Pack / titlePacks / StoryPack / assets / TitleAssets / assets / StringAssetInfo / value Итак, я сделал:

<xsl:template match="TitleReference[key('titleId', @id)/assets/TitleAssets/assets/StringAssetInfo[@attrId = '127']/value = $values]" />

, но это не работает.

XML:

<?xml version="1.0" encoding="UTF-8"?>
<Pack>
  <titlesPacks>
    <StoryPack id="1111111">
      <assets>
        <TitleAssets>
             <assets>
               <StringAssetInfo attrId="127">
                  <value>A</value>
               </StringAssetInfo>
             </assets>
        </TitleAssets>
      </assets>
     </StoryPack>
    </titlesPacks>
    <referenceTable>
     <ReferenceTable>
      <titlesReferences>
        <TitleReference id = "1111111"/>
      </titlesReferences>
     </ReferenceTable>
    </referenceTable>
</pack>

мне нужно

  • удалить StoryPack где атрибут attrId из StringAssetInfo = 127 и value = A или B ... => Уже в порядке
  • удалить TitleReference где id значение атрибута = id значение атрибута удаленных узлов выше

1 Ответ

0 голосов
/ 23 октября 2019

Попробовать так?

XSLT 2.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="titleId" match="StoryPack" use="@id"/>

<!-- Values for which nodes must be deleted -->
<xsl:variable name="values">
    <value>A</value>
    <value>B</value>
    <value>C</value>
</xsl:variable>

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

<!-- Delete nodes with specific values -->
<xsl:template match="StoryPack[value = $values/value]"/>

<!-- Delete nodes with id from specific values -->
<xsl:template match="TitleReference[key('titleId', @id)/value = $values/value]" />

</xsl:stylesheet>

Я упростил определение переменной, поэтому он может работать в этой онлайн-демонстрации:https://xsltfiddle.liberty -development.net / jz1PuP9 - а также потому, что это проще.


Добавлено:

Ввиду обновленной структуры XML измените:

<xsl:template match="StoryPack[value = $values/value]"/>

до:

<xsl:template match="StoryPack[.//value = $values/value]"/>

или (предпочтительно) до:

<xsl:template match="StoryPack[assets/TitleAssets/assets/StringAssetInfo/value = $values/value]"/>

и изменить:

<xsl:template match="TitleReference[key('titleId', @id)/value = $values/value]" />

на:

<xsl:template match="TitleReference[key('titleId', @id)//value = $values/value]" />

или (предпочтительно) до:

<xsl:template match="TitleReference[key('titleId', @id)/assets/TitleAssets/assets/StringAssetInfo/value = $values/value]" />
...