freeMarker(十四)——XML处理指南之必要的XML处理
学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net
1.基本内容
假设程序员在数据模型中放置了一个XML文档,就是名为 doc 的变量。这个变量和DOM 树的根结点"document"对应。 真实的变量 doc 之后结构是非常复杂的, 大约类似DOM树。所以为了避免钻牛角尖,我们通过例子来看看如何使用。
通过名称来访问元素
这个FTL打印book的title:
<h1>${doc.book.title}</h1>
将会输出:
<h1>Test Book</h1>
正如你所看到的,doc 和 book 都可以当作哈希表来使用。你可以按照子变量的形式来获得它们的子结点。 基本上,你用描述路径的方法来访问在DOM树中的目标(元素title)。 你也许注意到了上面有一些是假象:使用 ${doc.book.title}, 就好像我们指示 FreeMarker 打印 title 元素本身, 但是我们应该打印它的子元素文本(看看 DOM 树)。 那也可以办到,因为元素不仅仅是哈希表变量,也是字符串变量。 元素结点的标量是从它的文本子结点级联中获取的字符串结果。然而,如果元素有子元素, 尝试使用一个元素作为标量会引起错误。比如${doc.book}将会以错误而终止。
该FTL打印2个chapter的title:
<h2>${doc.book.chapter[0].title}</h2>
<h2>${doc.book.chapter[1].title}</h2>
这里,book 有两个 chapter 子元素, doc.book.chapter 是存储两个元素结点的序列。 因此,我们可以概括上面的FTL,所以它以任意chapter的数量起作用:
<#list doc.book.chapter as ch>
<h2>${ch.title}</h2>
</#list>
但是如果只有一个chapter会怎么样呢?实际上, 当你访问一个作为哈希表子变量的元素时,通常 也可以是序列(不仅仅是哈希表和字符串),但如果序列只包含一个项, 那么变量也作为项目自身。所以,回到第一个示例中,它也会打印book的title:
<h1>${doc.book[0].title[0]}</h1>
但是你知道那里就只有一个 book 元素, 而且book也就只有一个title,所以你可以忽略那些 [0]。 如果book恰好有一个 chapter(否则它就是模糊的: 它怎么知道你想要的是哪个 chapter 的 title? 所以它就会以错误而停止),${doc.book.chapter.title} 也可以正常进行。 但是因为一个book可以有很多chapter,你不能使用这种形式。如果元素 book 没有子元素 chapter, 那么 doc.book.chapter 将是一个长度为零的序列, 所以用FTL <#list ...> 也可以进行。
知道这样一个结果是很重要的,比如,如果 book 没有 chapter,那么 book.chapter 就是一个空序列,所以 doc.book.chapter?? 就 不会 是 false,它就一直是 true!类似地,doc.book.somethingTotallyNonsense?? 也不会是 false。来检查是否有子结点,可以使用 doc.book.chapter[0]??(或doc.book.chapter?size == 0)。 当然你可以使用类似所有的空值处理操作符 (比如 doc.book.author[0]!"Anonymous" ),只是不要忘了那个 [0]。
现在我们完成了打印每个chapter所有的 para 示例:
<h1>${doc.book.title}</h1>
<#list doc.book.chapter as ch>
<h2>${ch.title}</h2>
<#list ch.para as p>
<p>${p}
</#list>
</#list>
将会输出:
<h1>Test</h1>
<h2>Ch1</h2>
<p>p1.1
<p>p1.2
<p>p1.3
<h2>Ch2</h2>
<p>p2.1
<p>p2.2
上面的FTL可以书写的更加漂亮:
<#assign book = doc.book>
<h1>${book.title}</h1>
<#list book.chapter as ch>
<h2>${ch.title}</h2>
<#list ch.para as p>
<p>${p}
</#list>
</#list>
最终,一个"广义的"子结点选择机制是: 模板列出所有示例XML文档的para:
<#list doc.book.chapter.para as p>
<p>${p}
</#list>
将会输出:
<p>p1.1 <p>p1.2 <p>p1.3 <p>p2.1 <p>p2.2
这个示例说明了哈希表变量选择序列子结点的做法 (在前面示例中的序列大小为1)。在这个具体的例子中,子变量 chapter 返回一个大小为2的序列 (因为有两个 chapter),之后子变量 para 在那个序列中选择 para 所有结点的子结点。
这种机制的一个负面结果是类似于 doc.somethingNonsense.otherNonsesne.totalNonsense 这样的东西会被算作是空序列,而且你也不会得到任何错误信息。
访问属性
这个XML和原来的那个是相同的,除了它使用title属性,而不是元素:
<!-- THIS XML IS USED FOR THE "Accessing attributes" CHAPTER ONLY! -->
<!-- Outside this chapter examples use the XML from earlier. -->
<book title="Test">
<chapter title="Ch1">
<para>p1.1</para>
<para>p1.2</para>
<para>p1.3</para>
</chapter>
<chapter title="Ch2">
<para>p2.1</para>
<para>p2.2</para>
</chapter>
</book>
一个元素的属性可以通过和元素的子元素一样的方式来访问, 除了你在属性名的前面放置一个@符号:
<#assign book = doc.book>
<h1>${book.@title}</h1>
<#list book.chapter as ch>
<h2>${ch.@title}</h2>
<#list ch.para as p>
<p>${p}
</#list>
</#list>
这会打印出和前面示例相同的结果。
按照和获取子结点一样的逻辑来获得属性,所以上面的 ch.@title 结果就是大小为1的序列。如果没有 title 属性,那么结果就是一个大小为0的序列。 所以要注意,这里使用内建函数也是有问题的:如果你很好奇 foo 是否含有属性 bar, 那么你不得不写 foo.@bar[0]??。 (foo.@bar?? 是不对的,因为它总是返回 true)。类似地,如果你想要一个 bar 属性的默认值,那么你就不得不写 foo.@bar[0]!"theDefaultValue"。
正如子元素那样,你可以选择多结点的属性。 例如,这个模板将打印所有chapter的title属性:
<#list doc.book.chapter.@title as t>
${t}
</#list>
探索DOM树
这个FTL将会枚举所有book元素的子结点:
<#list doc.book?children as c>
- ${c?node_type} <#if c?node_type == 'element'>${c?node_name}</#if>
</#list>
将会输出:
- text - element title - text - element chapter - text - element chapter - text
?node_type 的意思可能没有解释清楚。 有一些在DOM树中存在的结点类型,比如 "element", "text","comment", "pi"等。
?node_name 返回结点的结点名称。 对于其他的结点类型,也会返回一些东西,但是它对声明的XML处理更有用,这会在后面章节中讨论。
如果book元素有属性,由于实际的原因它可能 不会 在上面的列表中出现。 但是你可以获得包含元素所有属性的列表,使用变量元素的子变量 @@。如果你将XML的第一行修改为这样:
<book foo="Foo" bar="Bar" baaz="Baaz">
然后运行这个FTL:
<#list doc.book.@@ as attr>
- ${attr?node_name} = ${attr}
</#list>
然后得到这个输出(或者其他相似的结果):
- baaz = Baaz - bar = Bar - foo = Foo
要返回子结点的列表,有一个方便的子变量来仅仅列出元素的子元素:
<#list doc.book.* as c>
- ${c?node_name}
</#list>
将会输出:
- title - chapter - chapter
你可以使用内建函数 parent 来获得元素的父结点:
<#assign e = doc.book.chapter[0].para[0]>
<#-- Now e is the first para of the first chapter -->
${e?node_name}
${e?parent?node_name}
${e?parent?parent?node_name}
${e?parent?parent?parent?node_name}
将会输出:
para chapter book @document
在最后一行你访问到了DOM树的根结点,文档结点。 它不是一个元素,这就是为什么得到了一个奇怪的名字; 现在我们不来处理它。很明显,文档结点没有父结点。
你可以使用内建函数 root 来快速返回到文档结点:
<#assign e = doc.book.chapter[0].para[0]>
${e?root?node_name}
${e?root.book.title}
将会输出:
@document Test Book
在内建函数完整的列表中你可以用来在DOM树中导航, 可以阅读结点内建函数参考。
使用XPath表达式
title 是一个属性;仅对那部分使用。如果哈希表的键使用了结点变量而不能被解释(下一部分对此精确定义), 那么它就会被当作Xpath表达式被解释。要获得XPath的更多信息, 可以访问http://www.w3.org/TR/xpath。
例如,这里我们列出 title 元素(不是属性!)内容为"Ch1"的chapter的 para 元素:
<#list doc["book/chapter[title='Ch1']/para"] as p>
<p>${p}
</#list>
将会输出:
<p>p1.1 <p>p1.2 <p>p1.3
长度为1(在前面部分解释过了)的序列的规则也代表XPath的结果。 也就是说,如果结果序列仅仅包含1个结点,它也会当作结点自身。 例如,打印chapter元素"Ch1"第一段:
${doc["book/chapter[title='Ch1']/para[1]"]}
这也会输出相同内容:
${doc["book/chapter[title='Ch1']/para[1]"][0]}
XPath表达式的内容结点(或者是结点序列) 是哈希表子变量被用作发布XPath表达式的结点。 因此,这将打印和上面例子相同的内容:
${doc.book["chapter[title='Ch1']/para[1]"]}
请注意,现在你可以使用0序列或多(比1多)结点作为内容, 这只在程序员已经建立 FreeMarker 使用Jaxen而不是Xalan时才可以。
也要注意XPath序列的项索引从1开始,而FTL的序列项索引是用0开始的。 因此,要选择第一个chapter,XPath表达式是 "/book/chapter[1]", 而FTL表达式是 book.chapter[0]。
如果程序员设置 FreeMarker 使用Jaxen而不是Xalan, 那么 FreeMarker 的变量在使用XPath变量引用时是可见的:
<#assign currentTitle = "Ch1"> <#list doc["book/chapter[title=$currentTitle]/para"] as p> ...
请注意,$currentTitle 不是 FreeMarker 的插值, 因为那里没有 { 和 }。 那是XPath表达式。
一些XPath表达式的结果不是结点集,而是字符串,数字或者布尔值。 对于那些XPath表达式,结果分别是FTL字符串,数字或布尔值变量。 例如,下面的例子将会计算XML文档中 para 元素的总数, 所以结果是一个数字:
${x["count(//para)"]}
将会输出:
5
XML命名空间
默认来说,当你编写如 doc.book 这样的东西时, 那么它会选择属于任何XML命名空间(和XPath相似)名字为 book 的元素。如果你想在XML命名空间中选择一个元素, 你必须注册一个前缀,然后使用它。比如,如果元素 book 是命名空间 http://example.com/ebook, 那么你不得不关联一个前缀,要在模板的顶部使用 ftl 指令 的 ns_prefixes 参数:
<#ftl ns_prefixes={"e":"http://example.com/ebook"}>
现在你可以编写如 doc["e:book"] 的表达式。 (因为冒号会混淆 FreeMarker,方括号语法的使用是需要的。)
ns_prefixes 的值作为哈希表, 你可以注册多个前缀:
<#ftl ns_prefixes={
"e":"http://example.com/ebook",
"f":"http://example.com/form",
"vg":"http://example.com/vectorGraphics"}
>
ns_prefixes 参数影响整个 FTL 命名空间。 这就意味着实际中,你在主页面模板中注册的前缀必须在所有的 <#include ...> 的模板中可见,而不是 <#imported ...> 的模板(经常用来引用FTL库)。从另外一种观点来说, 一个FTL库可以注册XML命名空间前缀来为自己使用,而前缀注册不会干扰主模板和其他库。
要注意,如果一个输入模板是给定XML命名空间域中的, 为了方便你可以设置它为默认命名空间。这就意味着如果你不使用前缀, 如在 doc.book 中,那么它会选择属于默认命名空间的元素。 这个默认命名空间的设置使用保留前缀 D,例如:
<#ftl ns_prefixes={"D":"http://example.com/ebook"}>
现在表达式 doc.book 选择属于XML命名空间 http://example.com/ebook 的 book 元素。 不幸的是,XPath不支持默认命名空间。因此,在XPath表达式中, 没有前缀的元素名称通常选择不输入任何XML命名空间的元素。然而, 在默认命名空间中访问元素你可以直接使用前缀D,比如: doc["D:book/D:chapter[title='Ch1']"]。
请注意,当你使用默认命名空间时,那么你可以使用保留前缀 N 来选择不属于任意结点空间的元素。比如 doc.book["N:foo"]。这对XPath表达式不起作用, 上述的都可以写作 doc["D:book/foo"]。
不要忘了转义!
我们在所有的示例中都犯了大错。我们生成HTML格式的输出, HTML格式保留如 <,& 等的字符。所以当我们打印普通文本(比如标题和段落)时, 我们不得不转义它,因此,示例的正确版本是:
<#escape x as x?html>
<#assign book = doc.book>
<h1>${book.title}</h1>
<#list book.chapter as ch>
<h2>${ch.title}</h2>
<#list ch.para as p>
<p>${p}
</#list>
</#list>
</#escape>
所以如果book的标题是"Romeo & Julia", 那么HTML输出的结果就是正确的:
... <h1>Romeo & Julia</h1> ...
2.具体细节
每一个和DOM树中单独结点对应的变量都是结点和哈希表类型的多类型的变量 (对于程序员:实现TemplateNodeModel 和 TemplateHashModel 两个接口)。因此,你可以使用结点内建函数来处理它们。 哈希表的键被解释为XPath表达式,除了在下面表格中显示的特殊键。 一些结点变量也有字符串类型,所以你可以使用它们作为字符串变量 (对于程序员:他们需要实现 TemplateScalarModel 接口)。
结点类型 (?node_type) |
结点名称 (?node_name) |
字符串值 (比如 <p>${node}) |
特殊哈希表键 |
|---|---|---|---|
"document" |
"@document" |
没有字符串值。(当你尝试用字符串来使用时发生错误。) | "elementName", "prefix:elementName", "*", "**", "@@markup", "@@nested_markup", "@@text" |
"element" |
"name": 元素的名称。这是本地命名(也就是没有命名空间前缀的名字)。 |
如果它没有子元素,所有子结点的文本串联起来。 当你尝试用它当字符串时会发生错误。 | "elementName", "prefix:elementName", "*", "**", "@attrName", "@prefix:attrName", "@@", "@*", "@@start_tag", "@@end_tag", "@@attributes_markup", "@@markup", "@@nested_markup", "@@text", "@@qname" |
"text" |
"@text" |
文本本身。 | "@@markup", "@@nested_markup", "@@text" |
"pi" |
"@pi$target" |
在目标名称和 ?> 之间的部分。 |
"@@markup", "@@nested_markup", "@@text" |
"comment" |
"@comment" |
注释的文本,不包括分隔符 <!-- 和 -->。 |
"@@markup", "@@nested_markup", "@@text" |
"attribute" |
"name": 属性的名字。这是本地命名(也就是没有命名空间前缀的名字)。 |
属性的值。 | "@@markup", "@@nested_markup", "@@text", "@@qname" |
"document_type" |
"@document_type$name": name 是文档元素的名字。 |
没有字符串值。(当你尝试用字符串来使用时发生错误。) | "@@markup", "@@nested_markup", "@@text" |
注意:
没有CDATA类型,CDATA结点被透明地认为是文本结点。
变量 不 支持
?keys和?values。元素和属性结点的名字是本地命名,也就是,它们不包含命名空间前缀。 结点所属的命名空间的URI可以使用内建函数
?node_namespace来获得。XPath表达式需要Jaxen(推荐使用,但是请使用1.1-beta-8之后的版本; 可以从此处下载) 或者Apache的Xalan库,否则会有错误并且终止模板的执行。要注意, 隐藏在XPath表达式中一些特殊哈希表键有相同的意思, 尽管没有XPath可用的实现,但那些XPath表达式仍然会起作用。 如果Xalan和Jaxen两者都可用, FreeMarker 将会使用Xalen,除非你在Java代码中通过调用
freemarker.ext.dom.NodeModel.useJaxenXPathSupport()方法,才会使用Jaxen。如果Jaxen被用来支持XPath(而不是Xalan), 那么 FreeMarker 变量通过XPath变量的引用是可见的 (比如
doc["book/chapter[title=$currentTitle]"])。
特殊哈希表键的含义:
"elementName","prefix:elementName": 返回元素名为elementName的子结点的序列。(注意这里的"子"结点就是 直接 后继) 选择是XML命名空间的标识,除非XML文档用不再命名空间标识结点中的XML解析器解析。 在XML命名空间标识结点中,不含前缀的名字(elementName) 仅仅选择不属于任何XML命名空间的元素(除非你已经注册了默认的XML命名空间), 有前缀的名字(prefix:elementName) 选择属于前缀代表命名空间的元素。前缀的注册和默认XML命名空间的设置是由ftl指令 的ns_prefixes参数完成的。"*":返回所有子(直接后继) 元素 结点的序列。这个序列会按"文档顺序"包含元素, 也就是说,按照每个XML结点的表现形式的第一个字符的顺序出现 (在一般实体的扩展之后)。"**":返回所有后继 元素 结点的序列。这个序列按文档顺序包含元素。"@attName","@prefix:attrName": 作为一个大小为1,包含属性结点的序列的形式,返回元素的属性名attName,如果属性不存在时, 作为一个空序列返回(所以来检查属性是否存在,可以使用foo.@attName[0]??, 而不是foo.@attName??)。 正如"elementName"这个特殊的键, 如果序列的长度为1,那么它也当作是第一个子变量。如果没有使用prefix,那么它只返回属性, 而不使用XML命名空间(尽管你已经设置了默认的XML命名空间)。 如果使用了prefix, 它返回仅仅属于关联的prefix的XML命名空间的属性。前缀的注册是由ftl指令 的ns_prefixes参数完成的。"@@"或"@*":返回属于父结点的结点的属性序列,这和XPath中的@*是相同。"@@qname":返回元素的完全限定名 (比如e:book,和由?node_name返回的本地名book形成对比)。使用的前缀 (如e)是基于在当前命名空间用ftl指令的ns_prefixes参数注册的前缀而选择的, 而不受源XML文档中使用的前缀影响。如果你已经设置了一个默认的XML命名空间, 那么结点会使用默认的,前缀D就会被使用了。 不属于任何XML命名空间的结点,不使用前缀(尽管你设置过默认的命名空间)。 如果结点没有为命名空间注册的前缀,那结果是不存在的变量 (node.@@qname??是false)。"@@markup":这会以字符串形式返回一个结点的完整XML标记。 (完整的XML标记表示它也包含子结点的标记,而且包含子结点的子结点的标记,以此类推) 你得到的标记和在源XML文档中的标记相比不是必须的,它只是语义上的相同。特别地, 注意CDATA段将会解释成普通文本。也要注意基于你是怎么用包装原生的XML文档的, 注释或处理指令结点可能被移除,而且它们将会从源文件的输出中消失。 对于在输出XML段的每个XML命名空间,第一个被输出的开始标记将会包含xmlns:prefix属性, 而且那些前缀将会在输出的元素和属性名中使用。这些前缀和使用ftl指令的ns_prefixes参数注册的前缀相同 (没有前缀使用D,因为它会和xmlns属性被用来注册默认的命名空间),如果XML命名空间没有定义前缀, 那么会使用一个任意未被选择使用的前缀。"@@nested_markup":这个和"@@markup"相似,但是它返回不包括开放和封闭标记元素的XML标记。对于文档结点,它返回和"@@markup"相同的内容。对于其他类型结点(文本,处理指令等), 它返回一个空字符串。不像"@@markup",在输出中没有xmlns:prefix属性, 但是关于在元素和属性名中使用前缀规则是相同的。"@@text":它返回文本结点(所有后继文本结点, 而不是直接子结点)点的值,连接成一个单独的字符串。 如果结点没有子文本结点,那么返回的是空字符串。"@@start_tag":返回元素结点 开始标签 的标记。 正如@@markup,输出和源XML文档相比不是必须的, 但是在语义上是相同的。关于XML命名空间 (输出中的xmlns:prefix属性等), 规则和"@@markup"是相同的。"@@end_tag":返回元素结点 结束标签 的标记,正如@@markup,输出和源XML文档相比不是必须的, 但是在语义上是相同的。@@attributes_markup:返回元素结点 属性 的标记,正如@@markup,输出和源XML文档相比不是必须的, 但是在语义上是相同的。
结点序列
许多特殊哈希表的键(指的是上面所有的列表), 和XPath表达式的结果是结点集(参考XPath 推荐), 返回结点的序列。
这些结点序列,如果它们只存储一个子变量,也会当作子变量本身。 例如,如果 book 元素只有一个 title 子结点,${book.title[0]} 和 ${book.title} 是相同的。
返回一个空结点序列是普通的情形。例如,如果一个确定的XML文档, book 元素没有子元素 chapter, 那么 book.chapter 的结果就是一个空的结点序列。 要小心!这也意味着 book.chaptre(注意打字错误) 也会返回空的结点序列,而且会抛出错误而停止执行。同时, book.chaptre??(注意打字错误)将会返回 true,因为空的序列存在,所以你不得不使用 book.chaptre[0]?? 来检查。
结点序列存储的不是1个结点(但是0或者比1多的结点) 也会支持上面所描述的哈希表的键。那就是,下面这些特殊的键都是支持的:
"elementName","prefix:elementName""@attrName","@prefix:attrName""@@markup","@@nested_markup""@@text""*","**""@@","@*"
当在一个包含多于1个结点或0个结点序列里应用上面这些特殊的键中之一的时候, 那么对于序列(就是特殊的键可以起作用,比如文本结点对于键 * 或 @foo 将会被略过)中的每个结点, 这些特殊的键将会被应用于单独的结点,结果将会从最终的结果中被连接。 结果会被以和结点在序列中出现的对应顺序来连接。 连接就意味着字符串或序列的连接是基于结果类型之上的。 如果特殊的键会得到单独结点的字符串结果,那么对于多个结点的结果就是一个单独的字符串 (对单独结点的结果进行连接),而如果特殊的键返回单独结点的序列,那么对于多个结点, 结果就是一个单独的序列。如果在你应用特殊键的序列中没有结点,那么字符串结果就是空串, 而序列结果就是空序列。
XPath表达式可以和结点序列一同使用。然而,对于0或者大于1的结点, 因为Xalan对XPath实现的限制,仅仅你使用Jaxen代替Xalan时它才会起作用。
译自 Email: ddekany at users.sourceforge.net
freeMarker(十四)——XML处理指南之必要的XML处理的更多相关文章
- freeMarker(十五)——XML处理指南之声明的XML处理
学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net 1.基本内容 因为XML处理的方法非常必要--这在前面章节中已经展示- ...
- 全栈JavaScript之路( 二十四 )DOM2、DOM3, 不涉及XML命名空间的扩展
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/hatmore/article/details/37658167 (一)DocumentType 类型 ...
- 开发指南专题十四:JEECG微云高速开发平台MiniDao 介绍
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhangdaiscott/article/details/27068645 开发指南专题十四:J ...
- Gradle 1.12用户指南翻译——第三十四章. JaCoCo 插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- Gradle 1.12用户指南翻译——第六十四章. 发布到Ivy(新)
其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上的地址:https://gith ...
- BizTalk开发系列(十四) XML空白字符(WhiteSpace)
最近在做一个BizTalk项目,对XML文件的处理很复杂.本来是想找有没有方法可以一次性去除XML文件中节点和属性的值的空格.但是找了很久没有看到相关的方法.如果有知道该方法的麻烦跟我讲一下:cbcy ...
- Gradle 1.12用户指南翻译——第二十四章. Groovy 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
- Gradle 1.12用户指南翻译——第四十四章. 分发插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- SpringMVC(十四):SpringMVC 与表单提交(post/put/delete的用法);form属性设置encrypt='mutilpart/form-data'时,如何正确配置web.xml才能以put方式提交表单
SpringMVC 与表单提交(post/put/delete的用法) 为了迎合Restful风格,提供的接口可能会包含:put.delete提交方式.在springmvc中实现表单以put.dele ...
随机推荐
- POJ 1860
须要推断是否有正权环存在,Bellman-Ford算法就能够辣~ AC代码: #include <iostream> #include <cstdio> #include &l ...
- 用象棋的思维趣说IT人的职业发展和钱途
最近我花了不少功夫在学习象棋,也学习了王天一等高手的棋路,感觉IT人的职业和下棋一样,往好了讲,争主动权争实惠只争朝夕,往坏了讲,一步走错得用多步来弥补,如果错误太大未必能弥补回来.在本文里,就用下棋 ...
- An Ordinary Game(简单推导)
An Ordinary Game Time limit : 2sec / Memory limit : 256MB Score : 500 points Problem Statement There ...
- shu7-19【背包和母函数练习】
题目:http://acm.hdu.edu.cn/diy/contest_show.php?cid=20083 密码:shuacm 感觉他们学校的新生训练出的比较好. 今天很多题目都是强化了背包的转化 ...
- 教你管理SQL数据库系列(1-4)
原文 教你管理 SQL Server 数据库(1)数据库的结构 http://bbs.51cto.com/thread-1084951-1.html教你管理 SQL Server 数据库(2)系统数 ...
- Android 部分机型在三星S3上面出现了,sqlite莫名其名的锁住的问题
今天在使用安卓三星S3开发时.发现数据库老是锁住,其它机型并未出现锁住的问题,查看数据库所在的目录发现,和db文件同名的多出了一个文件以-journal结尾的莫名其妙的文件,怀疑是这个导致的所以在程序 ...
- 在vi或vim上查找字符串
从开头搜索 在命令模式下,输入/你要查找的字符 按下回车,可以看到vim把光标移动到该字符处 再按n(小写)查看下一个匹配 按N(大写)查看上一个匹配, capslock切换大小写,也可以在小写状态下 ...
- Flex中容器的完全隐藏
在html中,但我们设置某个dom元素的display属性为none时,dom元素不可见且其占用空间从dom树上隐藏,而在Flex中,但我们把某个组件的visible属性visible设为false的 ...
- [原创]java WEB学习笔记33:Session 案例 之 购物车
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- P4103 [HEOI2014]大工程
题目 P4103 [HEOI2014]大工程 化简题目:在树上选定\(k\)个点,求两两路径和,最大的一组路径,最小的一组路径 做法 关键点不多,建个虚树跑一边就好了 \(sum_i\)为\(i\)子 ...