来自mochiweb xpath的模式匹配

时间:2014-10-16 04:23:56

标签: elixir

我正在尝试模式匹配运行mochixpath返回的这些值。模式显然是[elemName,htmlAttrs,children],但我真正需要的是以下值:UserNameA和"这是一条消息"

[{"tr", [{"bgcolor", "White"}],
  [{"td", [{"class", "Topic"}],
   [{"div", [],
    [{"a", [{"class", "lnkUserName"}, {"href", "/users/prof.aspx?u=27149"}],
      ["UserNameA"]
    }]
 }]},
 {"img", [{"alt", ""}, {"src", "/Images/Icons/userIcon.gif"}], []},     
 {"td", [{"class", "bHeader"}],
    [{"div", [{"style", "float:left;width:77%;"}],[
        {"a", [{"class", "PostDisplay"}],
          ["This is a message"]}]
    }]
 }]

基本上我使用xpath输出中的解析xml来获取用户名和他们发送的消息。我对elixir和模式匹配的概念很新,所以非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

输出有问题,因为当我将它复制到控制台时会出现语法错误,所以我假设你有tr,td,img和其他td。

模式匹配可用于以这种方式展开。假设您将整个数据放在变量Data中,您可以使用以下内容提取内容:

[TR] = Data,
{_Name, _Attrs, Contents} = TR.

现在内容又是一个节点列表:[Td1, Img, Td2],所以你可以这样做:

[Td1, Img, Td2] = Contents.

依此类推,直到你真正达到你的内容。但是编写这个非常繁琐,你可以使用递归代替。让我们定义contents函数,递归扫描元素。

contents({_Name, _Attrs, Contents}) ->
    case Contents of
        [] -> []; % no contents like in img tag
        [H | T] ->
            case is_tuple(H) of
                % tupe means list of children
                true -> lists:map(fun contents/1, [H | T]);
                % otherwise this must be a string
                _ -> [H | T]
            end
    end.

这将返回嵌套列表,但您可以在最后运行lists:flatten,如下所示:

Values = lists:flatten(contents(Data)).

答案 1 :(得分:0)

在您的示例中,卷曲和方括号不平衡。我想最后错过了}]

似乎表达式的深度可能会有所不同,因此您必须递归地探索它。下面的代码是这样做的,假设你会在类型" a"中找到信息。元素:

-module (ext).
-compile([export_all]).


extL(L) -> extL(L,[]).

extL([],R) -> R;
extL([H|Q],R) -> extL(Q, extT(H) ++ R).

extT({"a",PropL,L}) ->
    case proplists:get_value("class",PropL) of
        "lnkUserName" -> [{user_name, hd(L)}];
        "PostDisplay" -> [{post_display,hd(L)}];
        _ -> extL(L,[])
    end;
extT({_,_,L}) -> extL(L,[]).

使用您的示例返回proplist [{post_display,"This is a message"},{user_name,"UserNameA"}]