OpenCamera源码阅读之XML解析

最近在看OpenCamera的源码,表示受益很深,项目地址:https://github.com/almalence/OpenCamera

讲真,从来没有解析过XML ,虽然json很方便,但是遇到了,还是表示学习一下

assets 下的xml 文件  opencamera_modes.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>

	<mode id="single" name="single_mode_name" savename="">
		<icon		id="gui_almalence_mode_single"/>

	    <vf 		id="com.almalence.plugins.histogramvf"/> 
	    <vf 		id="com.almalence.plugins.barcodescannervf"/>   
	    <vf 		id="com.almalence.plugins.gridvf"/>
	    <vf 		id="com.almalence.plugins.zoomvf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.capture" />    
	
	    <processing	id="com.almalence.plugins.simpleprocessing" />    
	
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>
	
		<sku/>
		
		<howtotext  id=""/>
		
	</mode>
	
	<mode id="burstmode" name="burst_mode_name"  savename="">
	    
	    <icon		id="gui_almalence_mode_burst"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
		<vf 		id="com.almalence.plugins.zoomvf"/>
	    <vf 		id="com.almalence.plugins.histogramvf"/>
	    <vf 		id="com.almalence.plugins.barcodescannervf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>   
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.burstcapture" />    
	
	    <processing	id="com.almalence.plugins.simpleprocessing" />    
	
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>
	
		<sku/>
		
		<howtotext  id=""/>
		
	</mode>
	
	<mode id="expobracketing" name="expobracketing_mode_name"  savename="BKT">
	
	    <icon		id="gui_almalence_mode_expobracketing"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
	    <vf 		id="com.almalence.plugins.zoomvf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.expobracketingcapture" />    
	
	    <processing	id="com.almalence.plugins.simpleprocessing" />    
		
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>
	
		<sku/>
		
		<howtotext  id=""/>
	
	</mode>
	
	<mode id="hdrmode" name="hdr_mode_name"  savename="HDR">
	
	    <icon		id="gui_almalence_mode_hdr"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
	    <vf 		id="com.almalence.plugins.zoomvf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.expobracketingcapture" />    
	
	    <processing	id="com.almalence.plugins.hdrprocessing" />    
	
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>
	
		<sku 		id="plugin_almalence_hdr"/>
		
		<howtotext  id=""/>
	
	</mode>
	
	<mode id="nightmode" name="night_mode_name"  savename="NIGHT" nameHAL="super_mode_name"  savenameHAL="SUPER">
	
	    <icon		id="gui_almalence_mode_night"/>
	    <iconHAL	id="gui_almalence_mode_super"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
		<vf 		id="com.almalence.plugins.zoomvf"/>
		<vf 		id="com.almalence.plugins.focusvf"/>
		<vf 		id="com.almalence.plugins.infosetvf"/>
		<vf 		id="com.almalence.plugins.aeawlockvf"/>
		<vf 		id="com.almalence.plugins.gyrovf"/>
		
	    <capture 	id="com.almalence.plugins.nightcapture" />    
	
	    <processing	id="com.almalence.plugins.nightprocessing" />    
	
	    <filter/>    
	
		<export 	id="com.almalence.plugins.export"/>
		
		<howtotext  id=""/>

		<sku 		id="plugin_almalence_super"/>		
	</mode>
	
	<mode id="video" name="video_mode_name"  savename="">
	
	    <icon		id="gui_almalence_mode_video"/>
	    
	    <vf 		id="com.almalence.plugins.zoomvf"/>   
	    <vf 		id="com.almalence.plugins.gridvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.videocapture" />    
	
	    <processing	id="com.almalence.plugins.simpleprocessing" />    
	
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>

		<sku		id="plugin_almalence_video"/>
		
		<howtotext  id=""/>
			
	</mode>
	 
	<mode id="preshot" name="preshot_mode_name"  savename="PRESHOT">
	
	    <icon		id="gui_almalence_mode_backintime"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
	    <vf 		id="com.almalence.plugins.zoomvf"/>   
	    <vf 		id="com.almalence.plugins.histogramvf"/>
	    <vf 		id="com.almalence.plugins.barcodescannervf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.preshotcapture" />    
	
	    <processing id="com.almalence.plugins.preshotprocessing"/>    
	
	    <filter/>    
	
	    <export     id="com.almalence.plugins.export"/>

		<sku/>
		
		<howtotext  id="preshot_mode_howto"/>
			
	</mode>
	
	<mode id="multishot" name="multishot_mode_name"  savename="MS">
	
	    <icon		id="gui_almalence_mode_moving"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
	    <vf 		id="com.almalence.plugins.zoomvf"/>   
	    <vf 		id="com.almalence.plugins.histogramvf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.multishotcapture" />    
	
	    <processing id="com.almalence.plugins.multishotprocessing"/>    
	
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>

		<sku		id="plugin_almalence_moving_burst"/>
		
		<howtotext  id=""/>
			
	</mode>
	
	<mode id="panorama_augmented" name="panorama_mode_name"  savename="PANO">
	
	    <icon		id="gui_almalence_mode_panorama"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
	    <vf 		id="com.almalence.plugins.histogramvf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.panoramacapture_augmented" />
	
	    <processing id="com.almalence.plugins.panoramaprocessing"/>    
	
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>

		<sku		id="plugin_almalence_panorama"/>
		
		<howtotext  id=""/>
	</mode>

	<mode id="bestshotmode" name="bestshot_mode_name"  savename="BEST">
	    
	    <icon		id="gui_almalence_mode_bestshot"/>
	    
	    <vf 		id="com.almalence.plugins.gridvf"/>
		<vf 		id="com.almalence.plugins.zoomvf"/>
	    <vf 		id="com.almalence.plugins.histogramvf"/>
	    <vf 		id="com.almalence.plugins.focusvf"/>
	    <vf 		id="com.almalence.plugins.infosetvf"/>
	    <vf 		id="com.almalence.plugins.aeawlockvf"/>   
	    <vf 		id="com.almalence.plugins.gyrovf"/>
	
	    <capture 	id="com.almalence.plugins.bestshotcapture" />    
	
	    <processing	id="com.almalence.plugins.bestshotprocessing" />    
	
	    <filter/>    
	
	    <export 	id="com.almalence.plugins.export"/>
	
		<sku/>
		
		<howtotext  id=""/>
		
	</mode>
	
	<!--  Default plugin for initial start -->     
    <defaultmode id="single"/>

</config>	


如何解析,过程跟自己解析json其实是一样的,先读取文件,然后从头开始按父节点,字节点,key-value形式解析

入口是parse(Context context)方法,Google有提供XmlPullParser

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;


import com.almalence.opencam.cameracontroller.CameraController;


import android.content.Context;
import android.content.res.AssetManager;
import android.os.Build;
import android.util.Xml;

public class ConfigParser
{

	private static final String	ns				= null;
	private static List<Mode>	modes;

	private static ConfigParser	configParser;

	private static String		defaultModeID	= "";

	public static ConfigParser getInstance()
	{
		if (configParser == null)
		{
			configParser = new ConfigParser();
		}
		return configParser;
	}

	private ConfigParser()
	{
		modes = new ArrayList<Mode>();
	}

	public Mode getMode(String mode)
	{
		Iterator<Mode> iterator = modes.iterator();
		while (iterator.hasNext())
		{
			Mode tmp = iterator.next();
			if (mode.equals(tmp.modeID))
				return tmp;
		}
		return null;
	}

	public List<Mode> getList()
	{
		return modes;
	}

	public Mode getDefaultMode()
	{
		if (defaultModeID.isEmpty())
			defaultModeID = modes.get(0).modeID;
		return getMode(defaultModeID);
	}

	public boolean parse(Context context) throws XmlPullParserException, IOException
	{
		AssetManager assetManager = context.getAssets();
		InputStream in = null;
		try
		{
			in = assetManager.open("opencamera_modes.xml");
		} catch (IOException e)
		{
			return false;
		}

		try
		{
			if (modes != null && modes.size() > 0)
				modes.clear();
			XmlPullParser parser = Xml.newPullParser();
			parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
			parser.setInput(in, null);
			parser.nextTag();
			return readConfig(parser);
		} finally
		{
			in.close();
		}
	}

	private boolean readConfig(XmlPullParser parser) throws XmlPullParserException, IOException
	{
		parser.require(XmlPullParser.START_TAG, ns, "config");
		while (parser.next() != XmlPullParser.END_TAG)
		{
			if (parser.getEventType() != XmlPullParser.START_TAG)
			{
				continue;
			}
			String name = parser.getName();
			if (name.equals("mode"))
			{
				Mode tmp = readMode(parser);
				modes.add(tmp);
			} else if (name.equals("defaultmode"))
			{
				defaultModeID = readDefaultMode(parser);
			} else
			{
				skip(parser);
			}
		}
		return true;
	}

	private String readDefaultMode(XmlPullParser parser) throws XmlPullParserException, IOException
	{
		parser.require(XmlPullParser.START_TAG, ns, "defaultmode");
		String modeID = parser.getAttributeValue(null, "id");
		
		//set super mode by default on these devices
		if (CameraController.isNexus5or6 ||
		    CameraController.isFlex2 ||
		    CameraController.isOnePlusTwo||
		    CameraController.isGalaxyS7)
		{
			Iterator<Mode> it = modes.iterator();
			while(it.hasNext())
			{
				Mode mode = it.next();
				if(mode.modeID.contains("nightmode"))
					modeID = "nightmode";
			}
		}
		
		parser.nextTag();
		return modeID;
	}

	private Mode readMode(XmlPullParser parser) throws XmlPullParserException, IOException
	{
		parser.require(XmlPullParser.START_TAG, ns, "mode");

		Mode mode = new Mode();
		mode.modeID = parser.getAttributeValue(null, "id");
		mode.modeName = parser.getAttributeValue(null, "name");
		mode.modeSaveName = parser.getAttributeValue(null, "savename");
		
		if ((mode.modeNameHAL = parser.getAttributeValue(null, "nameHAL")) == null)
			mode.modeNameHAL = mode.modeName;
		if ((mode.modeSaveNameHAL = parser.getAttributeValue(null, "savenameHAL")) == null)
			mode.modeSaveNameHAL = mode.modeSaveName;

		while (parser.next() != XmlPullParser.END_TAG)
		{
			if (parser.getEventType() != XmlPullParser.START_TAG)
			{
				continue;
			}
			readTag(parser, mode);
		}
		return mode;
	}

	private void readTag(XmlPullParser parser, Mode mode) throws IOException, XmlPullParserException
	{
		String tag = parser.getName();
		parser.require(XmlPullParser.START_TAG, ns, tag);
		String id = parser.getAttributeValue(null, "id");
		if (tag.equals("icon") || tag.equals("iconHAL"))
		{
			if (tag.equals("iconHAL"))
			{
				if (id != null)
					mode.iconHAL = id;
				else
					mode.iconHAL = mode.icon;
			}
			else
			{
				if (id != null)
				{
					mode.icon = id;
					mode.iconHAL = id;
				}
			}
		}
		else if (tag.equals("vf"))
		{
			if (id != null)
				mode.VF.add(id);
		} else if (tag.equals("capture"))
		{
			if (id != null)
				mode.Capture = id;
		} else if (tag.equals("processing"))
		{
			if (id != null)
				mode.Processing = id;
		} else if (tag.equals("filter"))
		{
			if (id != null)
				mode.Filter.add(id);
		} else if (tag.equals("export"))
		{
			if (id != null)
				mode.Export = id;
		} else if (tag.equals("sku"))
		{
			if (id != null)
				mode.SKU = id;
		} else if (tag.equals("howtotext"))
		{
			if (id != null)
				mode.howtoText = id;
		}
		/*
		 * add additional tag processing here
		 */
		else
		{
			skip(parser);
			return;
		}
		parser.nextTag();
		return;
	}

	private void skip(XmlPullParser parser) throws XmlPullParserException, IOException
	{
		if (parser.getEventType() != XmlPullParser.START_TAG)
		{
			throw new IllegalStateException();
		}
		int depth = 1;
		while (depth != 0)
		{
			switch (parser.next())
			{
			case XmlPullParser.END_TAG:
				depth--;
				break;
			case XmlPullParser.START_TAG:
				depth++;
				break;
			default:
				break;
			}
		}
	}
}






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TinyXML 是一个用 C++ 实现的 XML 解析库,可以用于解析 OpenDRIVE 文件。以下是使用 TinyXML 解析 OpenDRIVE 文件的基本步骤: 1. 引入 TinyXML 库 可以从 TinyXML 官网上下载 TinyXML 的源代码,然后编译成静态库或动态库,或者直接将 TinyXML 的源代码添加到项目中。在代码中包含 TinyXML 的头文件即可使用。 2. 加载 OpenDRIVE 文件 使用 TinyXML 的 `LoadFile` 方法加载 OpenDRIVE 文件,如: ```c++ TiXmlDocument doc("opendrive.xml"); if (!doc.LoadFile()) { printf("Failed to load file\n"); return; } ``` 3. 遍历 XML 树 使用 TinyXML 的 `RootElement` 方法获取 XML 树的根节点,并使用 `FirstChildElement` 和 `NextSiblingElement` 方法遍历 XML 树。例如,要获取 OpenDRIVE 文件的道路信息,可以使用以下代码: ```c++ TiXmlElement* root = doc.RootElement(); TiXmlElement* roadElement = root->FirstChildElement("road"); while (roadElement) { // 处理道路信息 ... roadElement = roadElement->NextSiblingElement("road"); } ``` 4. 获取 XML 元素的属性和内容 使用 TinyXML 的 `Attribute` 方法获取 XML 元素的属性值,使用 `GetText` 方法获取 XML 元素的内容。例如,要获取道路的长度和 ID,可以使用以下代码: ```c++ double length = atof(roadElement->Attribute("length")); int id = atoi(roadElement->Attribute("id")); ``` 注意,属性值是字符串类型,需要使用 `atof` 或 `atoi` 等方法将其转换为数值类型。 5. 获取 XML 元素的子元素 使用 TinyXML 的 `FirstChildElement` 和 `NextSiblingElement` 方法获取 XML 元素的子元素。例如,要获取道路的左右边界信息,可以使用以下代码: ```c++ TiXmlElement* boundaryElement = roadElement->FirstChildElement("planView")->FirstChildElement("geometry"); while (boundaryElement) { const char* type = boundaryElement->Attribute("type"); if (strcmp(type, "line") == 0) { // 处理直线边界 ... } else if (strcmp(type, "arc") == 0) { // 处理圆弧边界 ... } boundaryElement = boundaryElement->NextSiblingElement("geometry"); } ``` 6. 完成解析并释放资源 完成解析后,需要释放 TinyXML 的资源,可以使用 `Clear` 方法清空 XML 树,并使用 `delete` 关键字释放内存。例如: ```c++ doc.Clear(); delete doc; ``` 以上就是使用 TinyXML 解析 OpenDRIVE 文件的基本步骤。需要根据实际情况进行调整和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值