def node_attribute_xy(G, attribute, nodes=None):
    """Return iterator of node-attribute pairs for all edges in G.

    Parameters
    ----------
    G: NetworkX graph

    attribute: key
       The node attribute key.

    nodes: list or iterable (optional)
        Use only edges that are adjacency to specified nodes.
        The default is all nodes.

    Returns
    -------
    (x,y): 2-tuple
        Generates 2-tuple of (attribute,attribute) values.

    Examples
    --------
    >>> G = nx.DiGraph()
    >>> G.add_node(1,color='red')
    >>> G.add_node(2,color='blue')
    >>> G.add_edge(1,2)
    >>> list(nx.node_attribute_xy(G,'color'))
    [('red', 'blue')]

    Notes
    -----
    For undirected graphs each edge is produced twice, once for each edge 
    representation (u,v) and (v,u), with the exception of self-loop edges 
    which only appear once.
    """
    if nodes is None:
        nodes = set(G)
    else:
        nodes = set(nodes)
    node = G.node
    for u, nbrsdict in G.adjacency_iter():
        if u not in nodes:
            continue
        uattr = node[u].get(attribute, None)
        if G.is_multigraph():
            for v, keys in nbrsdict.items():
                vattr = node[v].get(attribute, None)
                for k, d in keys.items():
                    yield uattr, vattr
        else:
            for v, eattr in nbrsdict.items():
                vattr = node[v].get(attribute, None)
                yield uattr, vattr
