public class Dom4jTest {
public static void main(String[] args) throws DocumentException {
String svgURI = System.getProperty("user.dir") + "/test.svg";
SAXReader reader = new SAXReader();
File file = new File(svgURI);
Document document = reader.read(file);
Element root = document.getRootElement();
List<Element> childElements = root.elements();
for (Element child : childElements) {
if ("g".equals(child.getQName().getName())) {
List<Element> gElements = child.elements();
for (Element gEle : gElements) {
if ("g".equals(gEle.getQName().getName())) {
List<Element> elements = gEle.elements();
for (Element e : elements) {
if ("dfg:desc".equals(e.getQName().getName())) {
System.out.println(e.getText());
}
}
}
}
}
}
}
}
batik配合XPath解析svg文件
<!-- SVG解析包 -->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-all</artifactId>
<version>1.12</version>
<type>pom</type>
</dependency>
<svg>
<rect x="1" y="1" width="1198" height="598"
fill="none" stroke="blue" stroke-width="1" />
<path d="M200,300 Q400,50 600,300 T1000,300"
fill="none" stroke="red" stroke-width="5" />
<g fill="black" >
<circle cx="200" cy="300" r="10"/>
<circle cx="600" cy="300" r="10"/>
<circle cx="1000" cy="300" r="10"/>
</g>
<g fill="#888888" >
<circle cx="400" cy="50" r="10"/>
<circle cx="800" cy="550" r="10"/>
</g>
<path d="M200,300 L400,50 L600,300 L800,550 L1000,300"
fill="none" stroke="#888888" stroke-width="2" />
</svg>
//You first load the XML as a Document:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("image.svg");
//Then you use XPath to select the desired nodes. The expression below selects the contents of the d attributes of all the path elements inside the file:
String xpathExpression = "//path/@d";
//Now we can instantiate the XPath processor and compile the expression:
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
XPathExpression expression = xpath.compile(xpathExpression);
//Since the expected result is a node-set (two strings), we evaluate the expression on the SVG document using XPathConstants.NODESET as the second parameter:
NodeList svgPaths = (NodeList)expression.evaluate(document, XPathConstants.NODESET);
//From there you can extract the first set of path data using:
svgPaths.item(0).getNodeValue();
Xpath元素定位
Xpath简介
XPath是XML Path的简称,它是一种用来确定XML(可扩展标记语言)文档中某部分位置的语言。Xpath也是一种表达式语言,它基于XML的树状结构,可以用来在整个树中来寻找指定的节点,因此它的返回值可能是节点,节点集合,原子值,以及节点和原子值的混合等。
Xpath定位方法
Xpath选取节点
/ |
表示从根节点开始选取 |
// |
表示选择任意位置的某个节点,而不考虑它们的位置 |
nodename |
选取此节点的所有子节点。 |
. |
选取当前节点。 |
.. |
选取当前节点的父节点。 |
@ |
选取属性。 |
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
| 路径表达式 | 结果 |
|---|---|
| bookstore | 选取 bookstore 元素的所有子节点。 |
| /bookstore | 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
| bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
| //book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
| bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
| //@lang | 选取名为 lang 的所有属性。 |
以html选择节点为例
由于
HTML文档本身就是一个标准的XML页面,因此我们可以使用XPath的语法来定位页面元素。
定位节点
/html/body/form/input |
查找form下所有input节点元素 |
//input |
查找html中所有input节点元素 |
使用通配符(*)选择未知的元素
XPath 通配符可用来选取未知的 XML 元素。
| 通配符 | 描述 |
|---|---|
* |
匹配任何元素节点。 |
@* |
匹配任何属性节点。 |
node() |
匹配任何类型的节点。 |
//form/* |
查找form下所有节点元素 |
//* |
查找html中所有节点元素 |
//*/input |
查找所有input节点元素 |
//title[@*] |
选取所有带有属性的 title 元素。 |
选择分支
对于存在多个元素时想唯一定位,可以使用
[]中括号来选择分支,下标从1开始
//*/td[7]/a[1] |
定位到第7个td元素中第1个a元素 |
//*/td[7]/span[2] |
定位到第7个td元素中第2个span元素 |
//*/td[last()]/a[last()] |
定位到最后一个td元素中最后一个a元素 |
//*/td[a] |
定位包含a元素的所有td元素 |
选择最后一个元素可以用
last()函数,但是选择第一个元素没有first()函数。
选择属性
还可以利用标签内的属性来加以区分定位,在<>开始标记内除标签外,其他都可以看做是属性.
//input[@name] |
定位所有含name属性的input元素 |
//input[@*] |
定位所有含属性的input元素 |
//input[@value='2'] |
定位出value属性值为2的input元素 |
//input[@type='vedio'][@value='1']或//input[@type='vedio' and @value='1'] |
多个属性定位 |
//input/@id |
返回所有input元素的id属性 |
选取若干路径
过在路径表达式中使用
|运算符,您可以选取若干个路径。
| 路径表达式 | 结果 |
|---|---|
| `//book/title | //book/price` |
| `//title | //price` |
| `/bookstore/book/title | //price` |
常用函数
- 字符串查找函数:
contains()contains(string1,string2),表示如果string1包含string2,则返回true,否则返回false。 - 获取元素的文本内容:
text() - 从起始位置匹配字符串:
starts-with()
更多函数可参考:
http://www.w3school.com.cn/xpath/xpath_functions.asp
//a[contains(@href,'baidu')] |
定位href属性中包含baidu的所有a元素 |
//a[text()='推广'] |
链接文本信息是推广的所有a元素 |
//a[starts-with(@href,'/ads')] |
链接href属性以/ads开始的所有a元素 |
//a[contains(text(),'推广')] |
链接文本信息包含推广的所有a元素 |
Xpath轴
上面这些方法都不能定位时,这时候就得考虑依据元素的父辈、兄弟或者子辈节点来定位了,这就需要用到Xpath轴,利用轴可定位某个相对于当前节点的节点集。
语法:
轴名称::标签名
| 轴名称 | 描述 |
|---|---|
ancestor |
选取当前节点的所有先辈(父、祖父等)。 |
ancestor-or-self |
选取当前节点的所有先辈(父、祖父等)以及当前节点本身。 |
attribute |
选取当前节点的所有属性。 |
child |
选取当前节点的所有子元素。 |
descendant |
选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self |
选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following |
选取文档中当前节点的结束标签之后的所有节点。 |
namespace |
选取当前节点的所有命名空间节点。 |
parent |
选取当前节点的父节点。 |
preceding |
选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling |
选取当前节点之前的所有同级节点。 |
self |
选取当前节点。 |
| 例子 | 结果 |
|---|---|
child::book |
选取所有属于当前节点的子元素的 book 节点。 |
attribute::lang |
选取当前节点的 lang 属性。 |
child::* |
选取当前节点的所有子元素。 |
attribute::* |
选取当前节点的所有属性。 |
child::text() |
选取当前节点的所有文本子节点。 |
child::node() |
选取当前节点的所有子节点。 |
descendant::book |
选取当前节点的所有 book 后代。 |
ancestor::book |
选择当前节点的所有 book 先辈。 |
ancestor-or-self::book |
选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点) |
child::*/child::price |
选取当前节点的所有 price 孙节点。 |
示例
XPath教程
hbase的rowkey设计
概述
HBase是一个K/V存储型NoSQL数据库,与一般k/v数据库不同的是,Hbase的value由rowkey、column family:qualifier和TimeStamp这个三个维度快速定位。
HBase中rowkey可以唯一标识一行记录,在HBase查询的时候,有两种方式:
- 通过get方式,指定rowkey获取唯一一条记录
- 通过scan方式,设置startRow和stopRow参数进行范围匹配
- 全表扫描,即直接扫描整张表中所有行记录
rowkey长度原则
rowkey是一个二进制码流,可以是任意字符串,最大长度64kb,实际应用中一般为10-100bytes,以byte[]形式保存,一般设计成定长。
建议越短越好,不要超过16个字节
rowkey散列原则
- 尽量不要将rowkey设计成连续的值,如时间戳;
- 为rowkey增加随机散列字段,使数据均衡分布在每个RegionServer;
- 如果没有散列字段,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。
什么是热点?
热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用.
rowkey唯一原则
必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的.
设计方法
- Salting: 指将随机数据添加到行键的开头。
- Hashing: 哈希会使同一行永远用一个前缀加盐。
- 反转: 以手机号为rowkey,可以将手机号反转后的字符串作为rowkey
- 时间戳反转:
Long.Max_Value - timestamp - 尽量保持 ColumnFamily 名称尽可能小,最好是一个字符
- 虽然详细的属性名称更易于阅读,但更喜欢使用较短的属性名称来存储在
HBase中。
参考链接
hbase数据版本
Hbase版本数量
Hbase版本数量分为最大版本数量和最小版本数量:
- HBase最大版本数量:HBase 通过 HColumnDescriptor 为每个列族配置要存储的最大行数版本。最大版本的默认值为1。最大版本的数量可能需要根据应用程序需求增加或减少。不建议将最高版本数设置为极高的级别(例如,数百个或更多)。
- HBase最小版本数量:与最大行版本数一样,HBase 通过 HColumnDescriptor 为每个列族配置要保留的最小行数版本。最小版本的默认值为0,这意味着该功能被禁用。行版本参数的最小数目与
生存时间参数一起使用,并且可以与行版本参数的数目组合在一起,以允许诸如“保留最多T分钟值的数据,最多N个版本,但是至少保留 M 个版本 “(其中M 是最小行版本数的值,M < N)。仅当对列族启用了生存时间并且必须小于行版本的数量时,才应设置此参数。
HBase 生存时间(TTL)
- ColumnFamilies 可以以
秒为单位来设置 TTL(Time To Live)长度,一旦达到到期时间,HBase 将自动删除行。 - 也支持设置时间以每个单元为基础生存。
- 单元 TTL 以毫秒为单位而不是秒。
- 单元 TTL 不能将一个单元的有效生命周期延长超过 ColumnFamily 级 TTL 设置。
测试
默认Hbase列族最多保存一个版本的数据,可以通过下面命令修改,也可以使用HColumnDescriptor:
alter 'test', NAME => 'cf', VERSIONS => 3
创建表的时候指定版本数量:
hbase(main):018:0> create 'test',{NAME=>'base_info',VERSIONS=>3 },{NAME=>'extra_info',VERSIONS=>1 }
0 row(s) in 4.2670 seconds
更多详细的用法可以参考help 'create':
hbase(main):016:0> help 'create'
Creates a table. Pass a table name, and a set of column family
specifications (at least one), and, optionally, table configuration.
Column specification can be a simple string (name), or a dictionary
(dictionaries are described below in main help output), necessarily
including NAME attribute.
Examples:
Create a table with namespace=ns1 and table qualifier=t1
hbase> create 'ns1:t1', {NAME => 'f1', VERSIONS => 5}
Create a table with namespace=default and table qualifier=t1
hbase> create 't1', {NAME => 'f1'}, {NAME => 'f2'}, {NAME => 'f3'}
hbase> # The above in shorthand would be the following:
hbase> create 't1', 'f1', 'f2', 'f3'
hbase> create 't1', {NAME => 'f1', VERSIONS => 1, TTL => 2592000, BLOCKCACHE => true}
hbase> create 't1', {NAME => 'f1', CONFIGURATION => {'hbase.hstore.blockingStoreFiles' => '10'}}
hbase> create 't1', {NAME => 'f1', IS_MOB => true, MOB_THRESHOLD => 1000000, MOB_COMPACT_PARTITION_POLICY => 'weekly'}
Table configuration options can be put at the end.
Examples:
hbase> create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']
hbase> create 't1', 'f1', SPLITS => ['10', '20', '30', '40']
hbase> create 't1', 'f1', SPLITS_FILE => 'splits.txt', OWNER => 'johndoe'
hbase> create 't1', {NAME => 'f1', VERSIONS => 5}, METADATA => { 'mykey' => 'myvalue' }
hbase> # Optionally pre-split the table into NUMREGIONS, using
hbase> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname)
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit', REGION_REPLICATION => 2, CONFIGURATION => {'hbase.hregion.scan.loadColumnFamiliesOnDemand' => 'true'}}
hbase> create 't1', 'f1', {SPLIT_ENABLED => false, MERGE_ENABLED => false}
hbase> create 't1', {NAME => 'f1', DFS_REPLICATION => 1}
You can also keep around a reference to the created table:
hbase> t1 = create 't1', 'f1'
Which gives you a reference to the table named 't1', on which you can then
call methods.
hbase默认端口说明
| 节点 | 端口号 | 协议 | 使用 | 说明 |
| zookeeper | 2181 | zkCli.sh -server zookeeper1:2181 | 客户端接入 | |
| 2888 | N/A | 集群内部通讯 | ||
| 3888 | N/A | 集群内部通讯 | ||
| HDFS Namenode | 9000 | HDFS | hdfs dfs -ls hdfs://namenode1:9000/ | 客户端接入 |
| 50070 | HTTP | http://namenode1:50070/ | 集群监控 | |
| HDFS SecondaryNamenode | 50090 | HTTP | http://namenode1:50090/ | secondary监控 |
| HDFS Datanode | 50010 | N/A | 客户端接入/其他节点接入 | |
| 50020 | N/A | |||
| 50075 | HTTP | http://datanode1:50075/ | 节点监控 | |
| HBase Master | 16000 | hbase-client-1.x.x.jar | RegionServer接入 | |
| 16010 | HTTP | http://namenode1:16010/ | 集群监控 | |
| HBase RegionServer | 16020 | N/A | 客户端接入 | |
| 16030 | HTTP | http://datanode1:16030/ | 节点监控 |