Удаление связанных элементов с использованием XSLT 1.0 - PullRequest
0 голосов
/ 26 апреля 2010

Я пытаюсь удалить компоненты Component из XML ниже, которые имеют дочерние файлы с расширением «config». Мне удалось выполнить эту часть, но мне также нужно удалить соответствующие элементы ComponentRef, которые имеют те же значения "Id", что и эти компоненты.

<Fragment>
  <DirectoryRef Id="MyWebsite">
    <Component Id="Comp1">
      <File Source="Web.config" />
    </Component>
    <Component Id="Comp2">
      <File Source="Default.aspx" />
    </Component>
  </DirectoryRef>
</Fragment>
<Fragment>
  <ComponentGroup Id="MyWebsite">
    <ComponentRef Id="Comp1" />
    <ComponentRef Id="Comp2" />
  </ComponentGroup>
</Fragment>

Основываясь на других ответах SO, я создал следующий XSLT для удаления этих компонентов:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="Component[File[substring(@Source, string-length(@Source)- string-length('config') + 1) = 'config']]" />
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

К сожалению, это не удаляет совпадающие элементы ComponentRef (то есть те, которые имеют одинаковые значения "Id"). XSLT удалит компонент с идентификатором «Comp1», но не ComponentRef с идентификатором «Comp1». Как мне добиться этого с помощью XSLT 1.0?

Ответы [ 2 ]

4 голосов
/ 26 апреля 2010

Довольно эффективный подход заключается в использовании xsl:key для идентификации идентификаторов компонентов конфигурации:

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

    <xsl:key name="configComponent" 
      match="Component[File/@Source[substring(., 
               string-length() - string-length('config') + 1) = 'config']]" 
      use="@Id" />

    <xsl:template match="Component[key('configComponent', @Id)]" /> 

    <xsl:template match="ComponentRef[key('configComponent', @Id)]" /> 

    <xsl:template match="@*|node()"> 
        <xsl:copy> 
            <xsl:apply-templates select="@*|node()"/> 
        </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet>
0 голосов
/ 26 апреля 2010

Как насчет этого?Я сделал небольшое изменение в вашем оригинале, чтобы упростить его (проще проверить, заканчивается ли атрибут @source на «config»).

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="Component[substring(@Source, string-length(@Source) - 5) = 'config']" />
    <xsl:template match="ComponentRef[//Component[substring(@Source, string-length(@Source) - 5) = 'config']/@Id = @Id]"/>
        <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

Это имеетшаблон, соответствующий любому ComponentRef, который имеет тот же атрибут Id, что и компонент, соответствующий предыдущему шаблону.Одна вещь - «//Component» не эффективна.Вы должны быть в состоянии заменить это чем-то более эффективным - я не знаю вашу структуру XML

...