SimpleXML抛出XmlPullParserException,没有理由地引发未终止的实体引用。

7 浏览
0 Comments

SimpleXML抛出XmlPullParserException,没有理由地引发未终止的实体引用。

我对问题的原因已经没有任何想法了..我在Android上使用SimpleXML,它抛出了以下的堆栈跟踪:\n

06-08 13:20:56.450: E/AndroidRuntime(2281): FATAL EXCEPTION: main
06-08 13:20:56.450: E/AndroidRuntime(2281): java.lang.RuntimeException: org.xmlpull.v1.XmlPullParserException: unterminated entity ref (position:TEXT ????T???????????????...@21:133 in java.io.BufferedReader@b6438630) 
06-08 13:20:56.450: E/AndroidRuntime(2281):     at com.example.stuff.manager.LevelManager.(LevelManager.java:32)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at com.example.stuff.fragment.MainMenuFragment.onClick(MainMenuFragment.java:138)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at android.view.View.performClick(View.java:2485)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at android.view.View$PerformClick.run(View.java:9080)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at android.os.Handler.handleCallback(Handler.java:587)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at android.os.Handler.dispatchMessage(Handler.java:92)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at android.os.Looper.loop(Looper.java:130)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at android.app.ActivityThread.main(ActivityThread.java:3683)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at java.lang.reflect.Method.invokeNative(Native Method)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at java.lang.reflect.Method.invoke(Method.java:507)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at dalvik.system.NativeStart.main(Native Method)
06-08 13:20:56.450: E/AndroidRuntime(2281): Caused by: org.xmlpull.v1.XmlPullParserException: unterminated entity ref (position:TEXT ????T???????????????...@21:133 in java.io.BufferedReader@b6438630) 
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.kxml2.io.KXmlParser.exception(KXmlParser.java:273)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.kxml2.io.KXmlParser.error(KXmlParser.java:269)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.kxml2.io.KXmlParser.pushEntity(KXmlParser.java:781)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.kxml2.io.KXmlParser.pushText(KXmlParser.java:849)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.kxml2.io.KXmlParser.nextImpl(KXmlParser.java:354)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.kxml2.io.KXmlParser.next(KXmlParser.java:1378)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.stream.PullReader.read(PullReader.java:105)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.stream.PullReader.next(PullReader.java:89)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.stream.NodeReader.readElement(NodeReader.java:111)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.stream.NodeReader.readRoot(NodeReader.java:85)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.stream.NodeBuilder.read(NodeBuilder.java:84)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.stream.NodeBuilder.read(NodeBuilder.java:71)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.core.Persister.read(Persister.java:562)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at org.simpleframework.xml.core.Persister.read(Persister.java:462)
06-08 13:20:56.450: E/AndroidRuntime(2281):     at com.example.stuff.manager.LevelManager.(LevelManager.java:27)
06-08 13:20:56.450: E/AndroidRuntime(2281):     ... 12 more

\n从以下XML文件加载:\n



    
        
        
        
        
    


\n我使用以下POJO作为XML中内容的容器:\nFruitData.java:\n

@Root
public class Fruitdata
{
@Attribute
private Integer id;
@Attribute
private Integer row;
@Attribute
private Integer column;
public Integer getId()
{
    return id;
}
public void setId(Integer id)
{
    this.id = id;
}
public int getRow()
{
    return row;
}
public void setRow(int row)
{
    this.row = row;
}
public int getColumn()
{
    return column;
}
public void setColumn(int column)
{
    this.column = column;
}
}

\nFruitDatas.java:\n

@Root
public class Fruitdatas
{
@ElementList
private List fruitdatas;
public Fruitdatas()
{
}
public Fruitdatas(@ElementList(name = "fruitdatas") List fruitdatas)
{
    this.fruitdatas = fruitdatas;
}
public List getFruitdatas()
{
    return fruitdatas;
}
public void setFruitdatas(List fruitdatas)
{
    this.fruitdatas = fruitdatas;
}
}

\nLevel.java:\n

@Root
public class Level
{
@Attribute
private Long id;
@Attribute
private Long time;
@ElementList
private List fruitdatas;
public Long getId()
{
    return id;
}
public void setId(Long id)
{
    this.id = id;
}
public Long getTime()
{
    return time;
}
public void setTime(Long time)
{
    this.time = time;
}
public List getFruitdatas()
{
    return fruitdatas;
}
public void setFruitdatas(List fruits)
{
    this.fruitdatas = fruits;
}   
}

\nLevels.java:\n

@Root
public class Levels
{
@ElementList
private List levels;
public Levels()
{
}
public Levels(@ElementList(name = "levels") List levels)
{
    this.levels = levels;
}
public List getLevels()
{
    return levels;
}
public void setLevels(List levels)
{
    this.levels = levels;
}
}

\n加载发生在这里:\n

public LevelManager()
{
    Serializer serializer = new Persister();
    Levels levels = null;
    BufferedReader br = null;
    try
    {
        br = new BufferedReader(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("res/xml/levels.xml")));
        levels = serializer.read(Levels.class, br);
    }
    catch (Exception e)
    {
        Log.e(getClass().getSimpleName(), "Error in deserialization.", e);
        throw new RuntimeException(e);
    }
    finally
    {
        if (br != null)
        {
            try
            {
                br.close();
            }
            catch (IOException e)
            {
            }
        }
    }
    if (levels != null)
    {
        this.levels = levels.getLevels();
    }
}

\n我也尝试过只使用InputStream,但是我得到了相同的错误。\n我搜索了答案,但总是发现XML中有未转义的字符。我甚至检查了抛出异常的xml解析器的源代码,但它对我没有多大帮助:\n

723     private final void More ...pushEntity()
724         throws IOException, XmlPullParserException {
725 
726         push(read()); // &
727         
728         
729         int pos = txtPos;
730 
731         while (true) {
732             int c = read();
733             if (c == ';')
734                 break;
735             if (c < 128
736                 && (c < '0' || c > '9')
737                 && (c < 'a' || c > 'z')
738                 && (c < 'A' || c > 'Z')
739                 && c != '_'
740                 && c != '-'
741                 && c != '#') {
742                 if(!relaxed){
743                     error("unterminated entity ref");
744                 }
745                 //; ends with:"+(char)c);           
746                 if (c != -1)
747                     push(c);
748                 return;
749             }
750 
751             push(c);
752         }
753 
754         String code = get(pos);
755         txtPos = pos - 1;
756         if (token && type == ENTITY_REF){
757             name = code;
758         }
759 
760         if (code.charAt(0) == '#') {
761             int c =
762                 (code.charAt(1) == 'x'
763                     ? Integer.parseInt(code.substring(2), 16)
764                     : Integer.parseInt(code.substring(1)));
765             push(c);
766             return;
767         }
768 
769         String result = (String) entityMap.get(code);
770 
771         unresolved = result == null;
772 
773         if (unresolved) {
774             if (!token)
775                 error("unresolved: &" + code + ";");
776         }
777         else {
778             for (int i = 0; i < result.length(); i++)
779                 push(result.charAt(i));
780         }
781     }

\n我不知道!relaxed是什么意思。因此,我完全无法想到如何解决这个问题。\n有人之前遇到过这个问题吗?我可能做错了什么?我甚至连我的XML都是有效的。我认为我也正确地注释了这些类。有什么想法吗?\n编辑:显然我的调试感觉到了,我将缓冲区读入的内容通过System.out发送出去。\n结果:\n

06-08 13:47:51.830: I/System.out(2334): ????T???????????????????????????????????h?????????????????????? ????????????????????????!??????'??????4??????@??????D??????J??????S??????W??????[??????_??????c??????g??????k??????o??????levels??id??time??level??1??400??
06-08 13:47:51.830: I/System.out(2334): fruitdatas??        fruitdata??0??row??column??2??4??3??5??6??7??8??9??????$??????????????????????????????????????????????????L???????????????????????????????????????????????????????????????????????????????????????????????$????????????????????????????????????????????????$????????????????????????????????????????????????$??????????????????????????????????????????????????????????????????????????????????????????????????????????????????$????????????????????    ??????????????????????????????????????????????????????????????????????????????????????  ????????$????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????  ??????????????????????$??????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????$??????????????????????????????????????????????????????????????????????????????????????????????????????????????$????????????????????  ??????????????????????????????????????????????????????????????????????????????????????  ????????$?????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????
06-08 13:47:51.830: I/System.out(2334): ??????????????????????????????????????????????????????????????????????????????????????

\n我将尝试弄清楚为什么从流中读取的XML是无意义的....

0
0 Comments

SimpleXML throws XmlPullParserException, unterminated entity ref for no reason

最近我遇到了一个问题,经过我的调试,我终于找到了解决方法。原来,使用以下代码读取数据是一个非常糟糕的主意。

br = new BufferedReader(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("res/xml/levels.xml")));

解决方法是将XML文件放入/res/raw文件夹中,并使用原始资源方式打开它们。

public LevelManager(Context context)
{
    Serializer serializer = new Persister();
    Levels levels = null;
    BufferedReader br = null;
    try
    {
        br = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(R.raw.levels)));
        levels = serializer.read(Levels.class, br);
    }
    catch (Exception e)
    {
        Log.e(getClass().getSimpleName(), "Error in deserialization.", e);
        throw new RuntimeException(e);
    }
    finally
    {
        if (br != null)
        {
            IOUtils.closeQuietly(br);
        }
    }
}

这样,文件的内容就可以正确地读取了。

希望这个解决方法能够帮助到其他人,不要再浪费时间在这个问题上了。

另外,我还需要添加`inline=true`,否则根据我的XML结构,它找不到数据。但这与问题没有直接关系。

0