XPath is my first contact in 2007, but it has only recently begun to generate interest. Before, in most cases, I will try to avoid using it, and when I had to try to use it, every failed. Then XPath for me does not make sense. But then I met a special resolution issue (of CSS selectors is too complicated, but the words of the code by hand is far too simple), so I decided to try again XPath. I was pleasantly surprised that this really works, but also useful. The following is a question of my personal experience I encountered assume you manage a lyrics website, in order to maintain a consistent reading experience, you have to collect the first word of each line of lyrics. If you save lyrics in plain text format, you can directly use the following code to achieve. ! lyrics.gsub (/^./) Christmas Angles iPhone 4 4S Cases {| character | character.upcase} But if the lyrics are saved Ken html format, there is no simple, because dom structure itself and no concept of 'row', so there is no way to use a simple The regular expressions to identify rows. So we need to do first thing is to define what is dom structure 'starting line' Here are two simple examples: \u0026 lt; p \u0026 gt; tags in the first text node \u0026 lt; br \u0026 gt; behind the first text node Michael Kors Clutches like this: \u0026 lt; p \u0026 gt; This is the beginning of a line \u0026 lt; br \u0026 gt; This is too \u0026 lt; / p \u0026 gt; but inline elements in addition we may have to deal with nested:.. \u0026 lt ; p \u0026 gt; \u0026 Michael Kors Hot Sale lt; em \u0026 gt; This \u0026 lt; / em \u0026 gt; is the beginning of a line \u0026 lt;. strong \u0026 gt;. This is not \u0026 lt; / strong \u0026 gt; \u0026 lt; / p \u0026 gt; conventional solutions I think the first solution is by Ruby dom write a method to scan all relevant parts and recursively find all the qualified nodes. Which uses several lightweight css selectors: def each_new_line (document) document.css ('p') each {| p | yield first_text_node (p)} document.css ('br') each {|.. br |?? yield first_text_node (br.next)} enddef first_text_node (node) if node.nil then nil elsif node.text then node elsif node.children.any then first_text_node (node.children.first) endend This is a relatively? reasonable solution, but 11 lines of code seems a bit long. Feeling a little overkill, just to get dom nodes and spend Ruby iterators and conditionals feel a bit not worthwhile. There should be a better way, right? Finally comes the question of the (XPath) XPath There are several reasons people get confused about. The first point is Michael Kors Accessories that the Internet is almost no reference to something (W3Schools! Would not have thought). RFC has the best documentation I find. The second point is the XPath looks a bit like CSS. Method name in there 'path', so I always assumed the XPath expression / and CSS selector of \u0026 gt; is a meaning. document.xpath ('// p / em / a') == document.css ('p \u0026 gt; em \u0026 gt; a') In fact, XPath expression contains a number of short, if we want to figure out the code to run on top of what happened it is necessary to clarify these shorthand. Here is the same expression with whole spelled out: / descendant-or-self :: node () / child :: p / child :: em / child :: a / the XPath expressions and above CSS selector effect is the same, but not as I had assumed that. An XPath expression is composed of one or more / split positioning step (location steps) components. The first expression / representatives of the document (document) of the root node. Each positioning step show already matched node and convey information about the three: I want to move from the current location where? The answer is that the shaft (Axis), is optional. The default axis is the child, said that 'the currently selected node of all child nodes.' In the above example, descendant-or-self is the first axis positioning unit, said that 'all currently selected nodes and all their child nodes.' Most XPath axes defined in the specification has semantic names such as 'descendant-or-self'. I want to choose what type of node? Selected content is specified by the node test, which is an indispensable step each positioning part. In our previous example, node () matches are all types; text () is matched to the text node; element () can only be matched to the elements, and must (like p, em, etc.), Michael Kors Handbags node name specified node name Required. Additional Christmas Beauty iPhone 4 4S Cases filters may increase it? Maybe we want to select all current node's first child element or just want to have a href attribute is selected \u0026 lt; a \u0026 gt; tags. For such assertion (assertion), we can use the predicate (predicates) according to an additional traversing the tree (additional tree traversals) to filter out qualified node. So that we can attribute these nodes (children, Michael Kors Bedford & Astor parents, or siblings) to filter out qualified node. No predicate our example, let us add a match only has href attribute of \u0026 lt; a \u0026 gt; tag: / descendant-or-self :: node () / child :: p / child :: em / child :: a [attribute :: href] Although the predicate looks like a bracket positioning step, but the predicate 'node test (node test)' part of a test more functionality than the positioning step nodes. XPath for a point of view with an enhanced compared to CSS selectors, XPath and convenience JQuery more similar. For example, we can put before the XPath expression into a form JQuery: $ Christmas Beauty iPhone 5 5S Cases (document) .find ('*') children ('p') children ('em') children ('a') filter.... ('[href]') the above code, the role we use JQuery methods and the shaft is the same: .children () corresponds to the axis of the child, .find () equivalent descendant. JQuery method selector Michael Kors New Arrivals in the equivalent XPath node tests, but unfortunately does not allow jQuery Select the text node. jQuery in .filter () method is equivalent XPath predicate, .children ('em') role is to match all match \u0026 lt; p \u0026 gt; tags to all \u0026 lt; em \u0026 gt; child element. It would appear, XPah much stronger than jQuery. Let us return to the problem of identifying Michael Kors Hamilton the line now we XPath works have in-depth knowledge of, let's use it to solve the problems mentioned before. First, we should first look at the problem simplify, only to find the first text node of each segment: / descendant-or-self :: node () / child :: p / child :: text () [position () = 1] above the role of the code are: 1. Find all the nodes in the document 2. find all of these nodes \u0026 lt; p \u0026 gt; child node 3. Look for these \u0026 lt; p \u0026 gt; text child node 4. retain only those nodes that match The first element of the conditions of note position () function in the code indicates that each \u0026 lt; p \u0026 gt; The first text child node instead of the entire document in the first \u0026 lt; p \u0026 gt; text child nodes. Next, in order to find the \u0026 lt; p \u0026 gt; is very deeply nested text node, we replaced the child descendant / descendant-or-self :: node () / child :: p / descendant :: text () [ position () = 1] The next problem is to identify the wrap, first we have to break this long list of codes downside (because too long), XPath is allowed to do so. After adding a new line to identify the code as follows: / descendant-or-self :: node () / child :: br / following-sibling :: node () [position = 1] / descendant-or-self :: text () [position () = 1] for each line of code meaning are: 1. Find all the nodes 2. Find these nodes \u0026 lt; br \u0026 gt; child node 3. Find these \u0026 lt; br \u0026 gt; of a sibling node 4. If The above is not taken into text nodes, then take their child nodes first text node so that we can simultaneously select \u0026 lt; p \u0026 gt; a new row after; and \u0026 lt; br \u0026 gt. Let the above code merged into one expression: (/ descendant-or-self :: node () / child Michael Kors Christmas Cases :: p | / descendant-or-self :: node () / child :: br / following-sibling: : node () [position = 1]) / descendant-or-self :: text () [position () = 1] Finally, we replace the shorthand into: (// p | // br / following-sibling :: node () [position = 1]) / descendant-or-self Christmas Angles iPhone 5 5S Cases :: text () [position = 1] So we put a complex concept with a simple expression represents out. If we want Cheap Michael Kors to add more on-line operation, we only Michael Kors Satchels need to implement the code matches the name added more elements on it. What do we get from what? Since we can to achieve a relatively straightforward Ruby XPath why choose it? In most cases, Ruby is used to write high-level code, such as business logic, integration of application components, describe complex domain model. As can be seen best Ruby code is used to describe the intent and not for implementation. So use Ruby to do some low-level or application-independent things (come to traverse the dom tree node specified property) makes egg pain. One advantage is its speed XPath: XPath traversal is implemented by libxml, and the speed of native code is very fast. For example I cited Michael Kors Designer above, compared with the Ruby implementations, XPath is actually much slower. I guess the reason leading to this situation is for the \u0026 lt; br \u0026 gt; to find the next element of the label. Because this action is actually screened out first \u0026 lt; br \u0026 gt; all with the same level of the elements behind them and then filtered out first. So XPath speed depends on your usage, but a bit difficult to get started. It is designed to let you use a simple idiomatic expressions to traverse the dom tool.XPath is a good tool