2017-07-30 7 views
1

Rスクリプトを使用して、非常に大きな(〜620 MB)XMLファイルから一度に1つのノードを抽出しようとしています。私がアクセスしたいそれぞれのメインノードは、異なる薬物に対応し、すべてのノードは互いに平行である。ファイル全体をメモリに読み込もうとすると、RのXMLパーサーでは機能しませんので、私の目的はファイル全体を一度に1つずつ処理することです。RのgetSibling()を呼び出してXMLファイルから単一ノードを抽出するとクラッシュする

大規模なXMLファイルを大幅に切り捨てて、 4ノードだけを含むサンプルファイル。このXMLファイルの先頭には、次のようになります。

<?xml version="1.0" encoding="UTF-8"?> 
<drugbank xmlns="http://www.drugbank.ca" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.drugbank.ca http://www.drugbank.ca/docs/drugbank.xsd" version="5.0" exported-on="2017-07-06"> 
<drug type="biotech" created="2005-06-13" updated="2016-08-17"> 
    <drugbank-id primary="true">DB00001</drugbank-id> 
    <drugbank-id>BTD00024</drugbank-id> 
    <drugbank-id>BIOD00024</drugbank-id> 
    <name>Lepirudin</name> 
    <description>Lepirudin is identical to natural hirudin except for substitution of leucine for isoleucine at the N-terminal end of the molecule and the absence of a sulfate group on the tyrosine at position 63. It is produced via yeast cells. Bayer ceased the production of lepirudin (Refludan) effective May 31, 2012.</description> 
    <cas-number>138068-37-8</cas-number> 
    <unii>Y43GF64R34</unii> 
    <state>liquid</state> 
    <groups> 
    <group>approved</group> 
    </groups> 

は、利用可能なオプションを検討し、私はすでに抽出物はXMLファイルからフィールドを希望することを書かれているRスクリプトを使用したいた(それは小さなXMLファイルのために働きます、大きなファイルでは失敗します)、RのXMLライブラリのgetSibling()関数を使用するのが最良の選択です。次のように例のjob.xmlファイルが始まること

f = system.file("exampleData", "job.xml", package = "XML") 
tt = as(xmlParse(f), "XMLHashTree") 
x = xmlRoot(tt, skip = FALSE) 
DesiredOutput <- getSibling(x) 
# I’m still not sure how to “walk” to the next sibling after the above process completes, since this example file only contains one node, and there is no simple way to increment a counter using the above code 

<!-- Initial Comment --> 
<gjob:Helping xmlns:gjob="http://www.gnome.org/some-location"> 
    <gjob:Jobs> 

    <gjob:Job> 
     <gjob:Project ID="3"/> 
     <gjob:Application>GBackup</gjob:Application> 
     <gjob:Category>Development</gjob:Category> 

     <gjob:Update> 
     <gjob:Status>Open</gjob:Status> 
     <gjob:Modified>Mon, 07 Jun 1999 20:27:45 -0400 MET DST</gjob:Modified> 
     <gjob:Salary>USD 0.00</gjob:Salary> 
     </gjob:Update> 

     <gjob:Developers> 
     <gjob:Developer> 
     </gjob:Developer> 
     </gjob:Developers> 

しかし、私は自分を置き換えている場合(http://svitsrv25.epfl.ch/R-doc/library/XML/html/addSibling.htmlから)次のコード例は、この例のファイルに単一のノードを抽出するために動作しますXMLファイル(ファイル全体の小型版、私は私のRスクリプトが正しく、それを処理するために実行して、それは、合法的なXML形式であることを確認している)、次のコードでは、Rがクラッシュ:

f = "MyTruncatedExampleFile.xml" -> this line causes R to crash 
tt = as(xmlParse(f), "XMLHashTree") 
x = xmlRoot(tt, skip = FALSE) 
DesiredOutput <- getSibling(x) 

誰かが私の小さなXMLファイルがクラッシュを引き起こす理由を提案することができますが、例のjob.xmlファイルは正しく実行されますか?あなたの洞察力に感謝します。

+0

これはrのバグでしょうか? –

答えて

0

明らかに、クラッシュの原因となっている切り詰められたXML内の宣言されていない名前空間の接頭辞によるものと思われます。xmlns="http://www.drugbank.ca"これを削除すると、メソッドはRをクラッシュしません。メモ:宣言されていない名前空間はXMLドキュメントで有効です。だから、この問題はXMLパッケージの作者に提起されるべきです。また、<drug>は切り詰められたXMLに兄弟を持たないため、の代わりにxmlChildren()が以下で使用されます。オリジナルのXMLを変更することなく、回避策として

# CRASHES 
f = "DrugBank.xml" 
tt = as(xmlParse(f), "XMLHashTree") 
x = xmlRoot(tt, skip = FALSE) 
DesiredOutput <- xmlChildren(x)[[1]] 
DesiredOutput 

# NO CRASHES 
f = "DrugBank_oth.xml"      # REMOVED UNDEFINED NAMESPACE PREFIX 
tt = as(xmlParse(f), "XMLHashTree") 
x = xmlRoot(tt, skip = FALSE) 
DesiredOutput <- xmlChildren(x)[[1]] 
DesiredOutput 

、あなたが/*/* WIHルートの子レベルに特別な名前空間とXPathの接頭辞を定義getNodeSetを検討してください。インデックス[[1]]は、すべてのノードではなく、最初のノードを取得するために使用されます。ここでは、ウェブが接頭辞として使用されますが、何でもかまいません。

# NO CRASHES 
f = "DrugBank.xml" 
doc = xmlParse(f) 
nmsp = c(web="http://www.drugbank.ca")  # DEFINE NAMESPACE PREFIX 

DesiredOutput <- getNodeSet(doc, "/*/*", nmsp)[[1]] 
DesiredOutput 

# <drug type="biotech" created="2005-06-13" updated="2016-08-17"> 
# <drugbank-id primary="true">DB00001</drugbank-id> 
# <drugbank-id>BTD00024</drugbank-id> 
# <drugbank-id>BIOD00024</drugbank-id> 
# <name>Lepirudin</name> 
# <description>Lepirudin is identical to natural hirudin except for 
#    substitution of leucine for isoleucine at the N-terminal 
#    end of the molecule and the absence of a sulfate group on 
#    the tyrosine at position 63. It is produced via yeast 
#    cells. Bayer ceased the production of lepirudin (Refludan) 
#    effective May 31, 2012.</description> 
# <cas-number>138068-37-8</cas-number> 
# <unii>Y43GF64R34</unii> 
# <state>liquid</state> 
# <groups> 
#  <group>approved</group> 
# </groups> 
# </drug> 
関連する問題