【问题标题】:How to fuse a specific type of nodes in XML data in R?如何在 R 中融合 XML 数据中特定类型的节点?
【发布时间】:2013-07-02 18:10:21
【问题描述】:

我有一本书的 XML 文件。主树具有 Body/Pagecolumn/Region/Paragraph/Line/Word 级别。但是,我对 Line 级别不感兴趣。有什么方法可以融合 Line 级别而不破坏 R 中使用 XML 包或任何其他包的 Word 级别?转换后,主树为Body/Pagecolumn/Region/Paragraph/Word

下面提供了 XML 数据的示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE DjVuXML>
<DjVuXML>
<BODY>
<OBJECT data="file://localhost//book1.djvu" height="1650" type="image/x.djvu" usemap="book1.djvu" width="1275">
<PARAM name="PAGE" value="book1_001.djvu"/>
<PARAM name="DPI" value="300"/>
<HIDDENTEXT>
<PAGECOLUMN>
<REGION>
<PARAGRAPH>
<LINE>
<WORD coords="1,2,3,4,5">Title</WORD>
</LINE>
</PARAGRAPH>
</REGION>
</PAGECOLUMN>
<PAGECOLUMN>
<REGION>
<PARAGRAPH>
<LINE>
<WORD coords="30,564,90,545,559">This</WORD>
<WORD coords="97,559,109,545,559">is</WORD>
<WORD coords="115,564,162,545,559">a</WORD>
</LINE>
</PARAGRAPH>
<PARAGRAPH>
<LINE>
<WORD coords="30,589,80,570,584">First</WORD>
<WORD coords="88,584,115,570,584">line</WORD>
<WORD coords="123,584,146,574,584">is</WORD>
</LINE>
<LINE>
<WORD coords="30,614,90,598,609">Second</WORD>
<WORD coords="97,609,143,595,609">line</WORD>
<WORD coords="148,614,168,595,609">is</WORD>
</LINE>
<LINE>
<WORD coords="30,640,56,626,640">Third</WORD>
<WORD coords="63,640,95,626,640">line</WORD>
<WORD coords="101,640,128,626,640">is</WORD>
</LINE>
</PARAGRAPH>
</REGION>
</PAGECOLUMN>
</HIDDENTEXT>
</OBJECT>
<MAP name="book1.djvu"/>
</BODY>
</DjVuXML>

谢谢。

【问题讨论】:

    标签: xml r merge word paragraph


    【解决方案1】:

    我喜欢简单的正则表达式解决方案,在这种情况下,它们可能是要走的路。通常使用XML,我们希望使用XSLT。这是一种用于转换XML 的语言。有一个 R 包 Sxslt 可用于转换 XML。这个想法是定义2个模板:

    1. 第一个模板是所谓的恒等变换。这会复制所有属性和节点。如果特定元素有更相关的模板,xslt 将使用该模板。
    2. 然后我们声明了一个与 LINE 更相关的模板。这无济于事。因此,对于除 LINE 之外的所有节点和属性,转换都会执行复制。

    这里是我的代码:

    # install package if needed
    # install.packages('Sxslt', repos = "http://www.omegahat.org/R")
    require(Sxslt)
    # define a transformation
    sltTemp <- '<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
     <xsl:template match="@* | node()">
       <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
       </xsl:copy>
    </xsl:template>
    
    <xsl:template match="LINE">
       <xsl:apply-templates/>
    </xsl:template>
    
    </xsl:stylesheet>'
    
    # assume your XML is text variable named xdata
    # you can also work on a parsed file if you like
    # xD <- xmlParse(xdata)
    # xsltApplyStyleSheet(xD, sltTemp)
    # gives same result
    
    require(XML)
    newxdata <- saveXML(xsltApplyStyleSheet(xdata, sltTemp))
    xmlParse(newxdata)
    <?xml version="1.0"?>
    <DjVuXML>
      <BODY>
        <OBJECT data="file://localhost//book1.djvu" height="1650" type="image/x.djvu" usemap="book1.djvu" width="1275">
          <PARAM name="PAGE" value="book1_001.djvu"/>
          <PARAM name="DPI" value="300"/>
          <HIDDENTEXT>
            <PAGECOLUMN>
              <REGION>
                <PARAGRAPH>
                  <WORD coords="1,2,3,4,5">Title</WORD>
                </PARAGRAPH>
              </REGION>
            </PAGECOLUMN>
            <PAGECOLUMN>
              <REGION>
                <PARAGRAPH>
                  <WORD coords="30,290,65,276,290">This</WORD>
                  <WORD coords="73,290,84,276,290">is</WORD>
                  <WORD coords="92,290,100,280,290">a</WORD>
                </PARAGRAPH>
                <PARAGRAPH>
                  <WORD coords="30,290,65,276,290">First</WORD>
                  <WORD coords="73,290,84,276,290">line</WORD>
                  <WORD coords="92,290,100,280,290">is</WORD>
                  <WORD coords="30,290,65,276,290">Second</WORD>
                  <WORD coords="73,290,84,276,290">line</WORD>
                  <WORD coords="92,290,100,280,290">is</WORD>
                  <WORD coords="30,290,65,276,290">Third</WORD>
                  <WORD coords="73,290,84,276,290">line</WORD>
                  <WORD coords="92,290,100,280,290">is</WORD>
                </PARAGRAPH>
              </REGION>
            </PAGECOLUMN>
          </HIDDENTEXT>
        </OBJECT>
        <MAP name="book1.djvu"/>
      </BODY>
    </DjVuXML>
    

    【讨论】:

    • 谢谢!看起来很棒!几个问题,我不能为 windows 安装它,我需要从源代码编译它吗?如果我理解你的代码,在这种情况下,代码是否仍然适用于这种转换&lt;xsl:apply-templates select="node()"/&gt;,我的意思是没有@*?
    • 不幸的是,我认为没有可用的 Windows 版本。第一个模板是所谓的恒等变换en.wikipedia.org/wiki/Identity_transform。这会复制所有属性和节点。如果特定元素有更相关的模板,xslt 将使用该模板。我们声明了一个与 LINE 更相关的模板。这无济于事。因此,对于除 LINE 之外的所有节点和属性,转换都会执行复制。结果是原始 XML 减去 LINE 部分。
    • 谢谢。我也在 Windows 上使用 R。我尝试使用 RStudio 从源代码安装,但出现此错误:请定义 LIB_XSLT
    • 我在 Linux 系统上试了一下,效果很好!我希望能解决 Windows 安装问题。
    • @user1609452 我只是编辑以在评论中添加您出色的解释。
    【解决方案2】:

    正确的方法是使用xml 包并进行节点融合。

    但是,对于您提供的示例 xml,您可能可以使用简单的 gsub(查找和替换)。

    类似的东西:

    xmlfile <- readLines("test.xml")
    newfile <- gsub("<LINE>|</LINE>", "", xmlfile)
    

    然后从那里出发。

    【讨论】:

    • 谢谢。不过,我会再等一会儿,看看是否还会出现模块化解决方案。
    【解决方案3】:

    使用grepl 删除所有行的类似解决方案:

    ll <- readLines(textConnection(txt))
    ll <- ll[!grepl("<LINE>|</LINE>" ,ll)]
    txt <- paste(ll, "\n", collapse="")
    xmlParse(txt,asText=TRUE)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      相关资源
      最近更新 更多