首页 > 解决方案 > 拆分 XML 节点?可能在 R

问题描述

我需要将一些 XML 转换为不同类型的 XML,但我做的不对。如果可能的话,我想在 R 中实现这一点,因为无论如何都会在那里进行进一步的处理。

这是我拥有的 XML:

<sp_list date="mm-dd-YYYY" no="XX" session="1">
  <sp_proceedings>
      <statement id="XYZ">
        <p class="speaker"><speaker id="ABC"><name>John Doe</name></speaker>John Doe:</p>
        <p>Some words of wisdom.</p>
        <name>Master of Ceremonies:</name>
        <p>Thank you. Next Speaker...</p>
      </statement>
  </sp_proceedings>
</sp_list>

如您所见,在“statement”节点内,有两个发言者:第一个(“John Doe”)带有发言者 ID 标记。另一个(“司仪”)是同一声明的一部分,但我需要以一种将两者都表示为单独声明的方式对其进行转换。

我现在想要实现的是:

<sp_list date="mm-dd-YYYY" no="XX" session="1">
  <sp_proceedings>
      <statement id="XYZ">
        <p class="speaker"><speaker id="ABC"><name>John Doe</name></speaker>John Doe:</p>
        <p>Some words of wisdom.</p>
      </statement>
      <statement>
        <p class="speaker"><speaker type="Master of Ceremonies"><name>Master of Ceremonies</name></speaker>Master of Ceremonies:</p>
        <p>Thank you. Next Speaker is…&lt;/p>
      </statement>
  </sp_proceedings>
</sp_list>

can(并且将)中的语句列表要长得多。如果有一个额外的发言者,我基本上想拆分语句节点,以便所有发言者都在他们自己的语句节点内,并且可以按照相同的方式进行处理。

我认为这将是 XSLT 的一项工作,但是在摆弄了一段时间之后,我没有掌握它的窍门,而且我用谷歌搜索的东西已经不多了。我试图简单地用相应的 XML 标签替换第二个发言者的 -Node(本质上是插入</statement><statement><p class="speaker"><speaker type="Master of Ceremonies">而不是名称标签),但是由于标签不匹配,这会导致 XML 处理稍后崩溃。

什么是开始的方式?XSLT 是通往这里的路吗?我将如何开始编写这样的东西?我的意思是,我读了很多关于它的作用,但我似乎没有使用正确的词汇来继续。我认为这将是一个有用的工具来掌握,只要我找到一种方法。欢迎任何建议。如前所述:R-Only 解决方案会很棒,但我愿意使用命令行 (unix) 或最适合任务的任何方式处理 XML。

太感谢了!

编辑:

在@Parfait 的非常有帮助的回答之后,我意识到每个发言者的段落数是随机变化的。可能有一段或 10 或 15 段。所以我将示例更改如下:

<sp_list date="mm-dd-YYYY" no="XX" session="1">
  <sp_proceedings>
      <statement id="XYZ">
        <p class="speaker"><speaker id="ABC"><name>John Doe</name></speaker>John Doe:</p>
        <p>Some words of wisdom.</p>
        <p>Some more words.</p>
        <p>And even more words.</p>
        <p>There are so many words.</p>
        <name>Master of Ceremonies:</name>
        <p>Thank you. Next Speaker...</p>
      </statement>
  </sp_proceedings>
</sp_list>

我想我必须确定

-nodes 直到 -tag 出现?

标签: rxmlxslt

解决方案


获得所需输出的一种可能性是将第一个结果与以下结果区分开来,如下所示:

<?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"/>

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

      <xsl:template match="statement">
        <xsl:for-each select="p[not(@class)]">
          <statement>
            <xsl:choose>
                <xsl:when test="position() = 1">
                    <xsl:copy-of select="../@id|../p[1]" />
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="spk" select="translate(preceding-sibling::name[1],':','')" />
                    <p class="{preceding-sibling::p[@class]/@class}">
                    <speaker type="{$spk}"><name><xsl:value-of select="$spk" /></name></speaker><xsl:value-of select="concat($spk,':')" /></p>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:copy-of select="." />
          </statement>
        </xsl:for-each>
      </xsl:template>

</xsl:stylesheet>

它的输出是:

<?xml version="1.0"?>
<sp_list date="mm-dd-YYYY" no="XX" session="1">
    <sp_proceedings>
        <statement id="XYZ">
            <p class="speaker">
                <speaker id="ABC">
                    <name>John Doe</name>
                </speaker>
            John Doe:</p>
            <p>Some words of wisdom.</p>
        </statement>
        <statement>
            <p class="speaker">
                <speaker type="Master of Ceremonies">
                    <name>Master of Ceremonies</name>
                </speaker>
            Master of Ceremonies:</p>
            <p>Thank you. Next Speaker...</p>
        </statement>
    </sp_proceedings>
</sp_list>

输入中的所有以下<p>-<name>对将像第二个输出一样<statement>输出。


推荐阅读