如果元素内的值与xslt匹配,如何在xml中移动元素?

时间:2016-01-13 13:10:39

标签: xml xslt

这个我现在正在奋斗几天。我可以解决这个难题的一小部分,但是当我试图将它合并到一个xslt样式表中时,我完全迷失了。

源xml看起来像这样(简化)

$ sudo pip install --proxy=http://yourproxy:yourport package_name

预期输出应如下所示:

<tr>
  <pic>
    <hs>
      <spot>
        <posit>
          <pan>28</pan>
          <tilt>44</tilt>
        </posit>
        <id>_flare</id>
      </spot>
      <spot>
        <posit>
          <pan>6</pan>
          <tilt>7</tilt>
        </posit>
      </spot>
      <spot>
        <posit>
          <pan>4</pan>
          <tilt>8</tilt>
        </posit>
        <id>Point01</id>
      </spot>
    </hs>
    <snd>
      <level>1</level>
      <sound>
        <loop>1</loop>
      </sound>
    </snd>
  </pic>
</tr>

我认为需要一些解释。只应将“id”与“hs”中的“_flare”匹配的“spot”移动并添加到“snd”元素中。它还必须重新格式化:

<tr>
  <pic>
    <hs>
      <spot>
        <posit>
          <pan>6</pan>
          <tilt>7</tilt>
        </posit>
      </spot>
      <spot>
        <posit>
          <pan>4</pan>
          <tilt>8</tilt>
        </posit>
        <id>Point01</id>
      </spot>
    </hs>
    <snd>
      <level>1</level>
      <sound>
        <loop>1</loop>
      </sound>
      <lf>
          <pos>
            <pan>28</pan>
            <tilt>44</tilt>
          </pos>
          <col>#ffffff</col>
      </lf>
    </snd>
  </pic>
</tr>

  <spot>
    <posit>
      <pan>28</pan>
      <tilt>44</tilt>
    </posit>
    <id>_flare</id>
  </spot>

我很欣赏正确的方向让我再次前进!

此致

AHG

4 个答案:

答案 0 :(得分:1)

怎么样:

XSLT 1.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="*"/>

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

<xsl:template match="spot[id='_flare']"/>

<xsl:template match="snd">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:apply-templates select="../hs/spot[id='_flare']" mode="add"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="spot" mode="add">
    <lf>
        <pos>
            <xsl:copy-of select="posit/pan | posit/tilt"/>
        </pos>
        <col>#ffffff</col>
    </lf>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8" method="xml" version="1.0" indent="yes"/>
    <!-- Catch-all templates -->
    <xsl:template match="@*|text()">
        <xsl:copy-of select="."/>
    </xsl:template>
    <xsl:template match="*">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:template>
    <xsl:template match="processing-instruction()">
        <xsl:copy/>
    </xsl:template>
    <!-- delete spot from the top -->
    <xsl:template match="spot[id[text()='_flare']]"/>
    <!-- add spot to the bottom -->
    <xsl:template match="snd">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <xsl:apply-templates select="//spot[id[text()='_flare']]" mode="addToBottom"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="spot[id[text()='_flare']]" mode="addToBottom">
        <lf>
            <pos>
                <xsl:apply-templates select="./posit/*"/>
            </pos>
            <col>#ffffff</col>
        </lf>
    </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

我在最后一个问题上找到了答案。

我的xslt样式表现在是:

<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="*"/>

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

<xsl:template match="spot[id='_flare']"/>

<xsl:template match="snd">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:apply-templates select="../hs/spot[id='_flare']" mode="add"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="spot" mode="add">
    <lf>
        <pos>
            <xsl:copy-of select="posit/pan | posit/tilt"/>
        </pos>
        <col>#ffffff</col>
    </lf>
</xsl:template>

<xsl:template match="id"/>

<xsl:template match="hs/spot" >
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
<id> <xsl:value-of select="concat('Point',count(preceding::spot)+1)"/> </id>
</xsl:element>
</xsl:template>


</xsl:stylesheet>

虽然可能有更聪明的方法......

答案 3 :(得分:0)

基于michael.hor257k的解决方案,您可以保持不变,只需添加一个模板来处理ID:

<xsl:template match="spot">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()[local-name()!='id']"/>
        <id>
            <xsl:text>Point</xsl:text>
            <xsl:value-of select="format-number(count(preceding-sibling::spot[not(id='_flare')])+1,'00')"/>
        </id>
    </xsl:copy>
</xsl:template>

旧的id将被忽略,每个元素都会从“Point01”开始获得一个新的。