Как объединить определенный тип узлов в XML-данных в R?

У меня есть XML-файл книги. Главное дерево имеет уровни Body/Pagecolumn/Region/Paragraph/Line/Word. Однако меня не интересует уровень Line. Есть ли способ объединить уровень Line, не разрушая уровень Word в R, используя пакет XML или любой другой пакет? После преобразования основным деревом будет 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>

Благодарю.

3 ответа

Решение

Мне нравятся простые решения регулярных выражений, и в этом случае они, вероятно, путь. В общем с 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>

Правильный способ будет использовать xml упаковать и сделать узлы слияния.

Тем не менее, для предоставленного вами образца XML, вы можете обойтись простым gsub (найти и заменить).

Что-то вроде:

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

И иди оттуда.

Аналогичное решение с использованием grepl удалить все строки:

ll <- readLines(textConnection(txt))
ll <- ll[!grepl("<LINE>|</LINE>" ,ll)]
txt <- paste(ll, "\n", collapse="")
xmlParse(txt,asText=TRUE)
Другие вопросы по тегам